From 26a15457357c292aa1f6b4e0fd415dd0da6403d7 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Thu, 8 Jan 2026 07:39:27 -0800 Subject: [PATCH 001/745] 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 002/745] 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 003/745] 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 004/745] 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 005/745] 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 006/745] 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 007/745] 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 008/745] 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 009/745] 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 010/745] 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 011/745] 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 012/745] 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 013/745] 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 014/745] 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 015/745] 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 016/745] 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 017/745] 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 018/745] 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 019/745] 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 020/745] 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 021/745] 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 022/745] 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 023/745] 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 024/745] 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 025/745] 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 026/745] 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 027/745] 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 028/745] 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 029/745] 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 030/745] 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 031/745] 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 032/745] 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 033/745] 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 034/745] 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 035/745] 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 036/745] 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 037/745] 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 038/745] 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 039/745] 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 040/745] 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 041/745] 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 042/745] 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 043/745] 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 044/745] 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 045/745] 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 046/745] 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 047/745] 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 048/745] 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 049/745] 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 050/745] 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 051/745] 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 052/745] 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 053/745] 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 054/745] 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 055/745] 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 056/745] 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 057/745] 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 058/745] 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 059/745] 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 060/745] 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 061/745] 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 062/745] 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 063/745] 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 064/745] 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 065/745] 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 066/745] 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 067/745] 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 068/745] 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 069/745] 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 070/745] 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 071/745] 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 072/745] 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 073/745] 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 074/745] 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 075/745] 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 076/745] 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 077/745] 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 078/745] 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 079/745] [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 080/745] [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 081/745] [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 082/745] [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 083/745] [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 084/745] [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 085/745] [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 086/745] 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 087/745] 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 088/745] 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 089/745] 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 090/745] 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 091/745] 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 092/745] 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 746c87243ae5a440395f0f2008247bdfafb2f62e Mon Sep 17 00:00:00 2001 From: joonas-001 Date: Tue, 25 Aug 2026 19:49:23 +0800 Subject: [PATCH 093/745] 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 094/745] 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 095/745] 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 096/745] 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 097/745] 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 098/745] 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 64092c925ecb3787967f939caae0bc50e98dcce1 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 26 Aug 2026 11:57:13 -0400 Subject: [PATCH 099/745] 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 100/745] 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 101/745] 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 102/745] 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 103/745] 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 104/745] 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 105/745] 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 106/745] 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 107/745] 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 108/745] 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 109/745] 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 110/745] 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 111/745] 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 112/745] 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 113/745] 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 114/745] 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 115/745] 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 116/745] 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 117/745] 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 f092d9af82d640cbe4c64dc757e2042007b92bde Mon Sep 17 00:00:00 2001 From: N1ark Date: Mon, 17 Aug 2026 16:18:46 +0200 Subject: [PATCH 118/745] 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 1595b5e0ed508bb2b0246d6c1f33808c6c84857a Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 23 Jun 2026 17:17:57 +0800 Subject: [PATCH 119/745] [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 120/745] [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 121/745] [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 122/745] [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 123/745] 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 124/745] 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 125/745] 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 126/745] 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 127/745] [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 128/745] [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 129/745] 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 130/745] 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 131/745] 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 132/745] 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 133/745] 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 134/745] 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 135/745] 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 136/745] 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 137/745] 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 138/745] [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 139/745] 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 140/745] 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 141/745] 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 142/745] 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 143/745] 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 144/745] 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 145/745] 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 146/745] 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 147/745] 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 148/745] 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 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 149/745] =?UTF-8?q?When=20trying=20to=20recover=20from=20`?= =?UTF-8?q?for<=E2=80=A6>=20dyn=20=E2=80=A6`=20don't=20unconditionally=20t?= =?UTF-8?q?reat=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 150/745] 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 151/745] 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 152/745] 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 153/745] 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 154/745] 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 155/745] 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 156/745] 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 157/745] 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 158/745] 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 159/745] 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 160/745] 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 161/745] 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 162/745] 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 c9e2b6709dabbc42d2a6214c32b4574986815152 Mon Sep 17 00:00:00 2001 From: Yukang Date: Mon, 7 Sep 2026 14:04:46 +0800 Subject: [PATCH 163/745] 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 164/745] 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 165/745] 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 166/745] 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 167/745] 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 168/745] 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 169/745] 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 170/745] 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 171/745] 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 172/745] 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 173/745] 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 174/745] 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 175/745] 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 176/745] 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 177/745] 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 178/745] 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 179/745] 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 180/745] 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 181/745] 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 182/745] 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 183/745] 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 184/745] 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 185/745] 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 186/745] 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 187/745] 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 188/745] 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 189/745] 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 190/745] 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 191/745] 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 192/745] 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 193/745] 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 194/745] 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 195/745] 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 196/745] 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 197/745] 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 198/745] 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 199/745] 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 200/745] 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 201/745] 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 202/745] 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 4c3c97f5aa4a628944df6ff3aa65be6c36c4a639 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 13 Sep 2026 15:15:33 +0100 Subject: [PATCH 203/745] 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 204/745] 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 205/745] 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 206/745] 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 207/745] 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 208/745] 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 209/745] 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 210/745] 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 211/745] 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 212/745] 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 213/745] 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 214/745] 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 215/745] 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 216/745] 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 217/745] 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 218/745] 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 219/745] 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 220/745] 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 221/745] 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 222/745] 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 223/745] 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 224/745] 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 225/745] 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 226/745] 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 227/745] 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 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 228/745] 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 229/745] 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 230/745] 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 231/745] 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 232/745] 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 233/745] 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 234/745] 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 235/745] 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 236/745] 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 01da50fc26d00a33b4f8bf23596877d96b6adf80 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 15 Sep 2026 18:44:09 -0700 Subject: [PATCH 237/745] 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 238/745] 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 239/745] 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 240/745] 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 241/745] 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 242/745] 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 243/745] 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 f68cc95efd2c639071fecc320771a3eabc579fa9 Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Wed, 16 Sep 2026 13:25:03 +0200 Subject: [PATCH 244/745] 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 ba736a028b6386b1c6069125bae336b137e81187 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 12 Sep 2026 01:05:31 +0200 Subject: [PATCH 245/745] 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 246/745] 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 247/745] 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 0b34b6ecbc09b3ad19391bdb8563ba6487a40061 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Thu, 17 Sep 2026 04:34:53 +0000 Subject: [PATCH 248/745] 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 249/745] 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 250/745] 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 251/745] 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 252/745] 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 253/745] 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 254/745] 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 255/745] 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 256/745] 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 257/745] 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 258/745] 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 259/745] 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 71ef655c92f036d6136bb1788eb26d00e67d3eae Mon Sep 17 00:00:00 2001 From: ltdk Date: Tue, 15 Sep 2026 23:59:29 -0400 Subject: [PATCH 260/745] 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 261/745] 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 262/745] 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 263/745] 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 264/745] 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 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 265/745] 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 266/745] 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 267/745] 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 268/745] 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 5edb259c652ce8bed8477ec54fa37cc48f3472eb Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 3 Sep 2026 15:59:41 -0400 Subject: [PATCH 269/745] 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 270/745] 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 271/745] 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 f330047c2b4d36fb62320277be57f9d2d01fc30b Mon Sep 17 00:00:00 2001 From: cezarbbb Date: Fri, 7 Aug 2026 17:01:51 +0800 Subject: [PATCH 272/745] 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 273/745] 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 274/745] 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 275/745] 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 276/745] 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 44d6e57165985b97a890d670a281deb15d008bf3 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 10:47:41 +0200 Subject: [PATCH 277/745] 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 278/745] 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 279/745] 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 280/745] 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 281/745] 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 282/745] 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 283/745] 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 284/745] 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 285/745] 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 286/745] 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 287/745] 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 288/745] 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 289/745] 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 290/745] 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 291/745] 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 292/745] 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 293/745] 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 294/745] 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 295/745] 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 296/745] 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 297/745] 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 298/745] 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 299/745] 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 300/745] 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 301/745] 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 302/745] 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 303/745] 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 304/745] 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 9f092518e89692b1c2490cb15688361b73b313e1 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 14:54:17 +0200 Subject: [PATCH 305/745] 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 306/745] 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 307/745] 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 308/745] 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 309/745] 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 310/745] 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 311/745] 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 312/745] 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 313/745] 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 314/745] 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 315/745] 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 316/745] 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 317/745] 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 318/745] 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 319/745] 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 320/745] 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 321/745] 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 322/745] 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 323/745] 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 324/745] 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 325/745] 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 326/745] 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 327/745] 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 328/745] 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 329/745] 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 330/745] 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 331/745] 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 332/745] 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 333/745] 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 334/745] 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 335/745] 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 336/745] 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 337/745] 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 338/745] 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 339/745] 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 340/745] 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 341/745] 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 342/745] 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 343/745] 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 344/745] 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 345/745] 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 346/745] 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 347/745] 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 348/745] 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 349/745] 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 350/745] 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 351/745] 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 352/745] 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 353/745] 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 354/745] 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 355/745] 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 356/745] 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 d79631f00f1fe0adfebd2420413767d5b4b61d73 Mon Sep 17 00:00:00 2001 From: kianalikasana Date: Sat, 19 Sep 2026 17:24:09 +0800 Subject: [PATCH 357/745] 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 358/745] 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 359/745] 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 360/745] 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 361/745] 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 362/745] 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 363/745] 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 364/745] 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 3b433cb0c237ae0077c0069db7802d144f7eee36 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sat, 19 Sep 2026 13:27:41 +0000 Subject: [PATCH 365/745] 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 366/745] 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 367/745] 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 368/745] 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 369/745] 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 bc5fd06c341bb75e473de55455d0b09d6268e234 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Sep 2026 16:25:47 +0200 Subject: [PATCH 370/745] 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 371/745] 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 372/745] 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 373/745] 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 374/745] 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 375/745] 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 376/745] 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 377/745] 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 88a1bbeff06cf5dc45968e55d0e021e0693215aa Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Sep 2026 18:31:48 +0200 Subject: [PATCH 378/745] 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 379/745] 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 380/745] 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 381/745] 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 382/745] 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 383/745] 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 384/745] 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 385/745] 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 386/745] 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 387/745] 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 9c1bd2de3001dcc0a4bbea6424951c8d6f84b7a3 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 23 Jul 2026 09:01:30 -0500 Subject: [PATCH 388/745] 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 389/745] 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 390/745] 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 391/745] 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 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 392/745] 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 393/745] 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 394/745] 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 395/745] 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 396/745] 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 397/745] 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 398/745] 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 399/745] 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 400/745] 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 401/745] 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 402/745] 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 403/745] 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 404/745] 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 405/745] 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 3cfab90ecbe8f8d8c105396dcc6f38988edef30c Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 20 Sep 2026 04:32:52 +0000 Subject: [PATCH 406/745] 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 407/745] 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 408/745] 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 409/745] 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 428aeee7d9dc358d1c611cbb8e59bf25d6af5307 Mon Sep 17 00:00:00 2001 From: Oleksandr Babak Date: Sun, 20 Sep 2026 11:35:25 +0200 Subject: [PATCH 410/745] 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 411/745] 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 412/745] `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 413/745] 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 414/745] 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 415/745] 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 416/745] 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 417/745] 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 418/745] 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 419/745] 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 420/745] 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 421/745] 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 422/745] 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 c654d4d01ac933b8841129f7ecf46a4ac92fc945 Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Sun, 20 Sep 2026 19:45:35 +0600 Subject: [PATCH 423/745] 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 424/745] 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 425/745] 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 426/745] 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 427/745] 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 428/745] 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 429/745] 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 13c1957e9c433006a19e314115159e538c3e444a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 20 Sep 2026 20:08:44 +0200 Subject: [PATCH 439/745] 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 440/745] 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 441/745] 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 442/745] 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 443/745] 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 444/745] 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 445/745] 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 23ba1fae5fec0b5535c4ea21d23ded2f2d7304a4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 21 Sep 2026 08:58:45 +1000 Subject: [PATCH 446/745] 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 447/745] 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 19a586258214f8dcd9a9febbe626aed0b1fce143 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Mon, 21 Sep 2026 00:35:52 -0400 Subject: [PATCH 448/745] 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 449/745] 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 450/745] 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 451/745] 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 452/745] 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 453/745] 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 454/745] 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 455/745] 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 456/745] 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 457/745] 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 458/745] 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 459/745] 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 df1b5c96717c5839af6c7fa314b55c046043dbfa Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 21 Sep 2026 08:57:51 +0100 Subject: [PATCH 460/745] `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 461/745] 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 462/745] 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 463/745] 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 464/745] 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 465/745] 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 466/745] 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 467/745] 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 468/745] 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 469/745] 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 470/745] 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 1e9b3bccbbcb3c0f298e59422c331cab092f03d0 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 21 Sep 2026 12:03:07 +0200 Subject: [PATCH 471/745] 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 472/745] 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 473/745] 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 474/745] 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 475/745] 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 919170b08cc014c8e85709dd80efeed2bac74562 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 21 Sep 2026 12:24:34 +0200 Subject: [PATCH 476/745] 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 477/745] 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 e53b292767ce546ce06e726302bcc0f6ccc0a66a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Sep 2026 22:44:58 +0200 Subject: [PATCH 595/745] 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 596/745] 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 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 597/745] 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 598/745] 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 599/745] 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 600/745] 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 df8fb0f5ad45c474597fa579988ccfb53aff855a Mon Sep 17 00:00:00 2001 From: jackh726 Date: Wed, 23 Sep 2026 01:57:54 +0000 Subject: [PATCH 601/745] 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 602/745] 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 e5e0b1057f9579198f4c536dcd2c2f7ad933cf75 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Wed, 23 Sep 2026 13:44:47 +1000 Subject: [PATCH 603/745] 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 604/745] 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 605/745] 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 606/745] 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 607/745] 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 608/745] 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 609/745] 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 610/745] 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 611/745] 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 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 612/745] 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 613/745] 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 614/745] 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 4858117c582c8a3b530a923862f4981c47399092 Mon Sep 17 00:00:00 2001 From: lapla Date: Mon, 14 Sep 2026 20:42:09 +0900 Subject: [PATCH 615/745] 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 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 616/745] 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 617/745] 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 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 618/745] 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 711d8619a0f38466e7c84f02acf699fb7b25a88b Mon Sep 17 00:00:00 2001 From: lapla Date: Mon, 14 Sep 2026 20:48:45 +0900 Subject: [PATCH 619/745] 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 620/745] 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 621/745] 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 622/745] 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 623/745] 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 624/745] 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 625/745] 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 626/745] 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 627/745] 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 628/745] 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 629/745] 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 630/745] 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 8201a7b4bd655461299236b4e7b815411f1a42e5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 6 Sep 2026 10:57:37 +0200 Subject: [PATCH 631/745] 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 632/745] 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 12a8eb2a7a19d50e2858d934da38fd0a212267c8 Mon Sep 17 00:00:00 2001 From: jackh726 Date: Tue, 15 Sep 2026 19:38:04 +0000 Subject: [PATCH 633/745] 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 634/745] 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 635/745] 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 636/745] 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 637/745] 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 638/745] 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 976fcac712d75fc7d9d32e8278a77eae96a07f67 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Mon, 21 Sep 2026 09:26:46 +0000 Subject: [PATCH 639/745] 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 640/745] 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 641/745] 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 642/745] 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 643/745] 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 644/745] 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 645/745] 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 646/745] 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 647/745] 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 648/745] 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 649/745] 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 650/745] 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 651/745] 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 652/745] `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 653/745] 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 654/745] 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 655/745] 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 656/745] 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 2ed1e372dae36015873ba21a8ab6e8252d442af1 Mon Sep 17 00:00:00 2001 From: Yukang Date: Thu, 24 Sep 2026 10:49:27 +0800 Subject: [PATCH 657/745] 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 8231458b2933cec3316be630127ececee8e96944 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 11 Aug 2026 10:50:56 +0200 Subject: [PATCH 658/745] 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 659/745] 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 660/745] 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 661/745] 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 662/745] 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 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 663/745] 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 664/745] 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 665/745] 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 666/745] 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 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 667/745] 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 96b181cdac89beb9ae230078007d4789dd68712e Mon Sep 17 00:00:00 2001 From: Jakub Chlanda Date: Thu, 3 Sep 2026 10:11:56 +0000 Subject: [PATCH 668/745] 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 8e8371121c32b1649ef81fb9f61f2848e692b0ba Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 17 Aug 2026 14:47:59 +0200 Subject: [PATCH 669/745] 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 670/745] 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 671/745] 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 672/745] 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 673/745] 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 674/745] 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 675/745] 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 676/745] 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 677/745] 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 678/745] 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 679/745] 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 680/745] 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 681/745] 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 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 682/745] 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 288a941096948e3a6d9e85b7628dcf9b12cab633 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 24 Sep 2026 16:53:39 +0200 Subject: [PATCH 683/745] 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 a391456e06ca69e27fed704e3c597a608109aea1 Mon Sep 17 00:00:00 2001 From: jackh726 Date: Tue, 15 Sep 2026 19:59:01 +0000 Subject: [PATCH 684/745] 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 685/745] 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 e0b4fd01c723c594f02026981e9d6634cf801a27 Mon Sep 17 00:00:00 2001 From: gmes23 Date: Thu, 24 Sep 2026 13:55:01 -0400 Subject: [PATCH 686/745] 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 687/745] 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 688/745] 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 4de84d7f2a2c490a83a4ff33a61aab9387d967b4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 24 Sep 2026 22:15:20 +0200 Subject: [PATCH 689/745] 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 690/745] 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 691/745] 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 692/745] 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 693/745] 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 694/745] 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 e10ba5d3d9f2879f5b47e66659792ad179d5ff1f Mon Sep 17 00:00:00 2001 From: Roland Xu Date: Fri, 25 Sep 2026 10:21:45 +0800 Subject: [PATCH 695/745] 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 696/745] 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 697/745] 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 698/745] 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 dbc472b15467e68cb138282a1b0af8b8cfc3f995 Mon Sep 17 00:00:00 2001 From: Roland Xu Date: Fri, 25 Sep 2026 13:15:25 +0800 Subject: [PATCH 699/745] 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 4b538231e35e6edbc13ed012dd788a8f432d73fd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 25 Sep 2026 09:32:43 +0200 Subject: [PATCH 700/745] 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 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 701/745] 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 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 702/745] 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 703/745] 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 704/745] 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 c6dc51196d5d387cf44837e9d75212462fb07e4f Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 24 Sep 2026 22:01:39 +0300 Subject: [PATCH 705/745] 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 bf9971d353ccc52291d892e1a988b68a36ec0ad6 Mon Sep 17 00:00:00 2001 From: ltdk Date: Fri, 25 Sep 2026 08:58:22 -0400 Subject: [PATCH 706/745] 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 707/745] 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 708/745] 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 709/745] 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 710/745] 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 711/745] 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 712/745] 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 713/745] 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 714/745] 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 21c62776cd1f7ce9a6b06744313d6282f1d0c21a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 21 Sep 2026 22:02:30 +0200 Subject: [PATCH 715/745] 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 716/745] 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 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 717/745] 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 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 718/745] 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 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 719/745] 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 720/745] 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 424d9ecb1a15b239ea85bcbb9126b12cfd5f6277 Mon Sep 17 00:00:00 2001 From: Daniel Smith Date: Mon, 11 May 2026 14:57:33 -0400 Subject: [PATCH 721/745] 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 722/745] 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 723/745] 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 724/745] 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 725/745] 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 726/745] 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 727/745] 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 728/745] 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 729/745] 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 730/745] 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 1d910ae376cf35835481f15cfab1561bc25a5e1b Mon Sep 17 00:00:00 2001 From: malezjaa Date: Sat, 26 Sep 2026 00:28:04 +0200 Subject: [PATCH 731/745] 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 465889bc3355eea0179a6ccb103f13053dd21a37 Mon Sep 17 00:00:00 2001 From: Ashutosh1910 Date: Sun, 13 Sep 2026 12:00:51 +0530 Subject: [PATCH 732/745] 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 8d8674117b8f1c3531c0860f3955ee6e816e7c18 Mon Sep 17 00:00:00 2001 From: tye-exe Date: Sat, 26 Sep 2026 08:26:50 +0000 Subject: [PATCH 733/745] 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 734/745] 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 a0de97917cf55252e6bd8506324b809386e439e9 Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Tue, 25 Aug 2026 14:36:20 +0600 Subject: [PATCH 735/745] 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 ff6341671f2ae918cd819c14d7d981a38c56911f Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Sat, 19 Sep 2026 12:15:24 +0600 Subject: [PATCH 736/745] 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 9fdcfdd5a19147574a8e55ec147ee38b624677e7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 26 Sep 2026 17:00:16 +0200 Subject: [PATCH 737/745] 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 738/745] 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 739/745] 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 38d0d1762beed5cb5512c66a01ef918de3b47b62 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sat, 20 Jun 2026 21:03:37 +0200 Subject: [PATCH 740/745] 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 faddebf35248c543587db20a2a1f8b558bd5b950 Mon Sep 17 00:00:00 2001 From: ltdk Date: Sat, 26 Sep 2026 14:43:04 -0400 Subject: [PATCH 741/745] 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 b90cbcbabf4f0af8b4710f7d33fa0ee04337acc8 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Fri, 25 Sep 2026 10:32:29 +0000 Subject: [PATCH 742/745] 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 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 743/745] 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 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 744/745] 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 31e49f2de08aab35ecd5d1d8987394cdf8b9bff5 Mon Sep 17 00:00:00 2001 From: Yilin Chen <1479826151@qq.com> Date: Mon, 28 Sep 2026 22:01:04 +0800 Subject: [PATCH 745/745] Add safety comments for alloc::str --- library/alloc/src/str.rs | 86 ++++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 34 deletions(-) diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index cd1c149c3c4fc..810b2d5c1f631 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,34 @@ 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) }; - // 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); + // 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); + + // 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(); + result.set_len(result_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(); - result.set_len(result_len); - } result } @@ -250,7 +255,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 +324,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 +337,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 +383,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 +806,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 +836,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 +997,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 +1014,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 +1037,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.
  • +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 3285cce3dad8e74b1ecaf98675cc8b218c900758 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 19 Sep 2026 16:30:33 +0200 Subject: [PATCH 478/745] 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 479/745] 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 480/745] 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 cda3cdf19ebd19f523a7943964d1a3d579b6a60b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 19 Sep 2026 19:45:01 +0200 Subject: [PATCH 481/745] 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 482/745] 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 483/745] 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 484/745] 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 485/745] 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 486/745] 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 487/745] 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 488/745] 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 489/745] 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 490/745] 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 491/745] 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 492/745] 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 493/745] 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 494/745] 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 495/745] "*. 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 496/745] 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 497/745] 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 498/745] 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 499/745] 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 c644bf30478a9bf19301f63061ab795a486227ea Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 21 Sep 2026 17:30:02 +0200 Subject: [PATCH 500/745] 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 501/745] 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 502/745] 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 503/745] 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 504/745] 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 505/745] 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 506/745] 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 507/745] 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 508/745] 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 509/745] 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 510/745] 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 511/745] 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 512/745] 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 513/745] 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 514/745] 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 515/745] 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 516/745] 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 517/745] 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 140373788f0130353a7b49238ccd14c59b8eb424 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 21 Sep 2026 14:20:15 -0400 Subject: [PATCH 518/745] 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 519/745] 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 520/745] 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 521/745] 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 522/745] 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 523/745] 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 524/745] 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 525/745] 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 526/745] 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 527/745] 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 528/745] 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 529/745] 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 530/745] 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 63dfd1cfe20e444d366083b0564df006664944a1 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Mon, 21 Sep 2026 02:39:48 -0400 Subject: [PATCH 531/745] 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 532/745] 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 533/745] 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 534/745] 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 535/745] 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 536/745] 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 537/745] 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 538/745] 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 539/745] 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 540/745] 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 541/745] 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 542/745] 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 543/745] 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 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 544/745] 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 545/745] 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 546/745] 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 547/745] 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 548/745] 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 549/745] 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 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 550/745] 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 551/745] 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 552/745] 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 553/745] 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 abcb9780d6d41fde73929b766238acc2b0582fa4 Mon Sep 17 00:00:00 2001 From: David Venhoek Date: Mon, 7 Sep 2026 14:09:09 +0200 Subject: [PATCH 554/745] 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 555/745] 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 556/745] 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 557/745] 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 558/745] `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 559/745] `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 560/745] 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 561/745] 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 bae45db91d526101fdba2f316491bfdde891c209 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Tue, 22 Sep 2026 13:00:32 +0000 Subject: [PATCH 562/745] 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 563/745] 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 564/745] 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 565/745] 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 566/745] 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 567/745] 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 568/745] 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 569/745] 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 570/745] 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 571/745] 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 572/745] 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 573/745] 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 574/745] 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 575/745] 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 576/745] 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 577/745] 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 578/745] 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 fc83fc885ddfef7c695c49e1be3af90655f4af44 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 9 Sep 2026 05:02:14 +0900 Subject: [PATCH 579/745] 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 580/745] 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 501b40c89d67530ed3b5b55335b202d5f5cab136 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Tue, 22 Sep 2026 13:15:17 -0400 Subject: [PATCH 581/745] 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 582/745] 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 583/745] 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 76c850e82b7ac6c81fefc4c1a82374f67ff02599 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Tue, 22 Sep 2026 20:42:24 +0200 Subject: [PATCH 584/745] document `#[rustc_dyn_incompatible_trait]` --- compiler/rustc_attr_ir/src/attribute_docs.rs | 60 +++++++++++++++++++ compiler/rustc_attr_ir/src/data_structures.rs | 2 +- .../rustc_dyn_incompatible_trait.rs | 8 +++ .../rustc_dyn_incompatible_trait.stderr | 18 ++++++ .../rustc_dyn_incompatible_trait2.rs | 52 ++++++++++++++++ 5 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 tests/ui/attributes/doc_examples/rustc_dyn_incompatible_trait.rs create mode 100644 tests/ui/attributes/doc_examples/rustc_dyn_incompatible_trait.stderr create mode 100644 tests/ui/attributes/doc_examples/rustc_dyn_incompatible_trait2.rs diff --git a/compiler/rustc_attr_ir/src/attribute_docs.rs b/compiler/rustc_attr_ir/src/attribute_docs.rs index 4d40cd6d52f16..a2b00c90b3028 100644 --- a/compiler/rustc_attr_ir/src/attribute_docs.rs +++ b/compiler/rustc_attr_ir/src/attribute_docs.rs @@ -223,3 +223,63 @@ const _: () = (); /// /// [`vtable_entries`]: ../rustc_middle/ty/struct.TyCtxt.html#method.vtable_entries const _: () = (); + +#[doc(attribute = "rustc_dyn_incompatible_trait", alias = "rustc_do_not_implement_via_object")] +/// Opts a trait out of [dyn compatibility]. +/// +/// This is useful to reserve the ability to add dyn incompatible supertraits or methods to a trait +/// in the future and to ensure the soundness of various constructs - see below for more about that. +/// +/// For example [`Field`], [`FnPtr`], [`Tuple`], [`TransmuteFrom`], [`Sized`] and [`Unsize`] must +/// be dyn incompatible because these traits describe properties and layouts of types that would +/// be invalid for trait objects. +/// +/// While making a trait dyn incompatible can also be done by including a (hidden and/or unstable) +/// dyn incompatible method in the trait, using `#[rustc_dyn_incompatible_trait]` should be +/// preferred because it is self-documenting and generates better error messages. +/// +/// # Example +/// +#[doc = include_example!("rustc_dyn_incompatible_trait")] +/// +/// # Unsafe traits and dyn (in)compatibility +/// +/// [Recall] that a trait object (`dyn Trait`) implements the base trait, its auto traits, and any supertraits of +/// the base trait. This means that it's possible to run into subtle soundness problems when relying +/// on the safety contract of a dyn compatible unsafe trait. See the following example: +/// +// ignore-tidy-odd-backticks +/// ```should_panic +#[doc = include_str!("../../../tests/ui/attributes/doc_examples/rustc_dyn_incompatible_trait2.rs")] +// ignore-tidy-odd-backticks +/// ``` +/// +/// A solution for this is to make `UnsafeTrait` dyn incompatible, forcing `LocalTrait` to also be +/// dyn incompatible so that a `dyn LocalTrait` cannot be formed. This is what we ended up doing for +/// [#154619]. +/// +/// [`Allocator`] has had similar problems with [`Clone`] ([#156920]) +/// but as we really wanted `dyn Allocator` to be a thing we ended up not making it dyn +/// incompatible -- we ended up moving the safety contract to [`AllocatorClone`] instead. +/// +/// See also [#156917] and [#160045] for more examples of this problem. +/// +/// See [`AttributeKind::RustcDynIncompatibleTrait`] for the internal representation of this attribute. +/// +/// [`Allocator`]: core::alloc::Allocator +/// [`AllocatorClone`]: core::alloc::AllocatorClone +/// [`Clone`]: core::clone::Clone +/// [`Field`]: core::field::Field +// FIXME: use core::ops::FnPtr once trickled down to beta +/// [`FnPtr`]: https://doc.rust-lang.org/nightly/core/ops/trait.FnPtr.html +/// [`Tuple`]: core::marker::Tuple +/// [`TransmuteFrom`]: core::mem::TransmuteFrom +/// [`Sized`]: core::marker::Sized +/// [`Unsize`]: core::marker::Unsize +/// [dyn compatibility]: https://doc.rust-lang.org/nightly/reference/items/traits.html#dyn-compatibility +/// [recall]: https://doc.rust-lang.org/nightly/reference/types/trait-object.html#r-type.trait-object.impls +/// [#154619]: https://github.com/rust-lang/rust/issues/154619 "`deref_patterns` is unsound due to `dyn` of subtrait of `DerefPure`" +/// [#156917]: https://github.com/rust-lang/rust/issues/156917 "`dyn Allocator` together with `Allocator + PartialEq` safety requirements leads to unsoundness" +/// [#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 _: () = (); diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index d722d515582dc..712ed41ae7759 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -1267,7 +1267,7 @@ pub enum AttributeKind { /// Represents the [`rustc_dump_vtable`](./attribute.rustc_dump_vtable.html) attribute. RustcDumpVtable(Span), - /// Represents `#[rustc_dyn_incompatible_trait]`. + /// Represents the [`rustc_dyn_incompatible_trait`](./attribute.rustc_dyn_incompatible_trait.html) attribute. RustcDynIncompatibleTrait(Span), /// Represents `#[rustc_effective_visibility]`. diff --git a/tests/ui/attributes/doc_examples/rustc_dyn_incompatible_trait.rs b/tests/ui/attributes/doc_examples/rustc_dyn_incompatible_trait.rs new file mode 100644 index 0000000000000..912cdef5b60bb --- /dev/null +++ b/tests/ui/attributes/doc_examples/rustc_dyn_incompatible_trait.rs @@ -0,0 +1,8 @@ +//@ dont-require-annotations: ERROR +//@ compile-flags: --crate-type lib -Z ui-testing=no +#![feature(rustc_attrs)] + +#[rustc_dyn_incompatible_trait] +pub trait DynIncompatible {} + +pub fn f(_x: &dyn DynIncompatible) {} diff --git a/tests/ui/attributes/doc_examples/rustc_dyn_incompatible_trait.stderr b/tests/ui/attributes/doc_examples/rustc_dyn_incompatible_trait.stderr new file mode 100644 index 0000000000000..c871061a57507 --- /dev/null +++ b/tests/ui/attributes/doc_examples/rustc_dyn_incompatible_trait.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `DynIncompatible` is not dyn compatible + --> $DIR/rustc_dyn_incompatible_trait.rs:8:15 + | +8 | pub fn f(_x: &dyn DynIncompatible) {} + | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/rustc_dyn_incompatible_trait.rs:5:1 + | +5 | #[rustc_dyn_incompatible_trait] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility +6 | pub trait DynIncompatible {} + | --------------- this trait is not dyn compatible... + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/attributes/doc_examples/rustc_dyn_incompatible_trait2.rs b/tests/ui/attributes/doc_examples/rustc_dyn_incompatible_trait2.rs new file mode 100644 index 0000000000000..fd8b3ec4e2761 --- /dev/null +++ b/tests/ui/attributes/doc_examples/rustc_dyn_incompatible_trait2.rs @@ -0,0 +1,52 @@ +//@run-fail +mod foreign_crate { + /// # Safety requirements + /// + /// If this type also implements `SafeTrait`, + /// then that implementation must always return `true`. + pub unsafe trait UnsafeTrait {} + unsafe impl UnsafeTrait for &T {} + + pub trait SafeTrait { + fn returns_true(&self) -> bool; + } + impl SafeTrait for &T { + fn returns_true(&self) -> bool { + (*self).returns_true() + } + } + + impl SafeTrait for u8 { + fn returns_true(&self) -> bool { + true + } + } + /// Safety: impl returns `true`. + unsafe impl UnsafeTrait for u8 {} + + pub fn function(x: impl UnsafeTrait + SafeTrait) { + // Can't panic, after all, `x: UnsafeTrait` + // guarantees `returns_true` actually returns `true` + assert!(x.returns_true()); + } +} + +use foreign_crate::{SafeTrait, UnsafeTrait, function}; + +pub trait LocalTrait: UnsafeTrait {} +impl LocalTrait for T {} + +// We can do this because `dyn LocalTrait` is a local type. +// But `LocalTrait: UnsafeTrait`, so `dyn LocalTrait: UnsafeTrait` holds, +// and we don't have to `unsafe impl` it. +impl SafeTrait for dyn LocalTrait { + fn returns_true(&self) -> bool { + false + } +} + +fn main() { + let x = 42_u8; + let y: &dyn LocalTrait = &x; + function(y); // panics +} From a91d256934cc9d62cd65972323246d243e8d7730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 22 Sep 2026 18:47:35 +0000 Subject: [PATCH 585/745] Update comment --- .../src/diagnostics/region_errors.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 9d795ff567087..6ded70f4c5100 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -399,7 +399,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { /// --> $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 + /// | -- - `x` is only valid in the function body /// | | /// | lifetime `'a` defined here /// LL | let y: &dyn Foo = x; @@ -409,13 +409,17 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { /// | `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 + /// note: `'static` lifetime requirement from `<(dyn o::Foo + 'static)>::hello` introduced here + /// --> $DIR/static-impl-obligation.rs:158:20 /// | /// LL | impl dyn Foo + 'static where Self: 'static { - /// | ^^^^^^^ `'static` requirement introduced here + /// | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + /// | | + /// | lifetime requirement introduced here /// LL | fn hello(&'static self) where Self: 'static {} - /// | ^^^^^^^ `'static` requirement introduced here + /// | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here + /// | | + /// | lifetime requirement introduced here /// ``` fn explain_impl_static_obligation( &self, From d296cf28bce858e6917efe12c941ce3d62dbcd23 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Tue, 15 Sep 2026 15:10:25 -0400 Subject: [PATCH 586/745] bootstrap: link the offload runtimes with the in-tree lld when it is built --- src/bootstrap/src/core/build_steps/llvm.rs | 48 ++++++++++++++++------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index f89ccb4c2a6a8..914c06272ba01 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -832,6 +832,40 @@ fn debuginfo_map_cflags(builder: &Builder<'_>, target: TargetSelection) -> Vec, + target: TargetSelection, + llvm_output: &LlvmOutput, + cfg: &mut cmake::Config, + ldflags: &mut LdFlags, +) { + // Apple has it's own ld64 linker, so don't use LLD on Darwin. + if target.contains("apple") { + return; + } + + if builder.config.llvm_use_linker.is_some() || !builder.config.lld_enabled || target.is_msvc() { + // Logic derived from `configure_llvm` + // ThinLTO is only available when building with LLVM, enabling LLD is required. + if builder.config.llvm_thin_lto { + ldflags.push_all("-fuse-ld=lld"); + } + return; + } + + let lld_bin = builder.ensure(Lld { target }).join("bin"); + ldflags.push_all(format!("-B{} -fuse-ld=lld", lld_bin.display())); + + if llvm_output.link_shared() { + // LLD in this case needs the LLVM lib, so tell where to look for it. + let mut dylib_path = helpers::dylib_path(); + dylib_path.insert(0, llvm_output.root_dir().join("lib")); + cfg.env(helpers::dylib_path_var(), t!(env::join_paths(&dylib_path))); + } +} + fn configure_cmake( builder: &Builder<'_>, target: TargetSelection, @@ -1180,13 +1214,8 @@ impl CommandLineStep for RustOffload { let mut cfg = cmake::Config::new(builder.src.join("compiler/rustc_llvm/llvm-wrapper/offload/")); - // Logic copied from `configure_llvm` - // ThinLTO is only available when building with LLVM, enabling LLD is required. - // Apple's linker ld64 supports ThinLTO out of the box though, so don't use LLD on Darwin. let mut ldflags = LdFlags::default(); - if builder.config.llvm_thin_lto && !target.contains("apple") { - ldflags.push_all("-fuse-ld=lld"); - } + try_link_with_in_tree_lld(builder, target, &llvm_output, &mut cfg, &mut ldflags); configure_cmake(builder, target, &mut cfg, true, ldflags, CcFlags::default(), &[]); @@ -1397,13 +1426,8 @@ impl CommandLineStep for OmpOffload { cflags.push_all(format!(" -I {inc_dir}")); } - // Logic copied from `configure_llvm` - // ThinLTO is only available when building with LLVM, enabling LLD is required. - // Apple's linker ld64 supports ThinLTO out of the box though, so don't use LLD on Darwin. let mut ldflags = LdFlags::default(); - if builder.config.llvm_thin_lto && !target.contains("apple") { - ldflags.push_all("-fuse-ld=lld"); - } + try_link_with_in_tree_lld(builder, target, &llvm_output, &mut cfg, &mut ldflags); if let Some(dir) = &cxx_lib_dir { ldflags.push_all(format!("-L{}", dir.display())); From 90d7327077f5eb03d90f0620c5cff62cdece950a Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Tue, 22 Sep 2026 20:58:11 +0200 Subject: [PATCH 587/745] Make it clear what the alignment needs to be for `deallocate` --- library/core/src/alloc/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 6069c468f96e4..a2c81364ed155 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -148,7 +148,8 @@ impl fmt::Display for AllocError { /// /// Some of the methods require that a `layout` *fits* a memory block or vice versa. This means /// that the following conditions must hold: -/// * the memory block must be *currently allocated* with alignment of [`layout.align()`], and +/// * the memory block must be *currently allocated* by the allocator, +/// * [`layout.align()`] must be the same as the alignment of the layout used to allocate the block, and /// * [`layout.size()`] must fall in the range `min ..= max`, where: /// - `min` is the size of the layout used to allocate the block, and /// - `max` is the actual size returned from [`allocate`], [`allocate_zeroed`], From 85110fbf422e438ba8ff23e3e76c85da3b5a50b7 Mon Sep 17 00:00:00 2001 From: malezjaa Date: Tue, 22 Sep 2026 22:03:03 +0200 Subject: [PATCH 588/745] implement LazyLock::(get_unchecked, get_unchecked_mut) and make counterparts on OnceLock public --- library/std/src/lib.rs | 1 + library/std/src/sync/lazy_lock.rs | 70 ++++++++++++++++++++++++++++--- library/std/src/sync/once_lock.rs | 46 ++++++++++++++++++-- 3 files changed, 108 insertions(+), 9 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 3f853df52bc53..59734e2402373 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -369,6 +369,7 @@ #![feature(maybe_dangling)] #![feature(maybe_uninit_array_assume_init)] #![feature(maybe_uninit_fill)] +#![feature(once_lazy_lock_get_unchecked)] #![feature(panic_can_unwind)] #![feature(panic_internals)] #![feature(pin_coerce_unsized_trait)] diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index f150d42a3137c..d1e5fd0af66f1 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -197,14 +197,14 @@ impl T> LazyLock { guard.0.once.set_state(OnceExclusiveState::Complete); core::mem::forget(guard); // SAFETY: We put the value there above. - unsafe { &mut this.data.get_mut().value } + unsafe { LazyLock::get_unchecked_mut(this) } } let state = this.once.state(); match state { OnceExclusiveState::Poisoned => panic_poisoned(), // SAFETY: The `Once` states we completed the initialization. - OnceExclusiveState::Complete => unsafe { &mut this.data.get_mut().value }, + OnceExclusiveState::Complete => unsafe { LazyLock::get_unchecked_mut(this) }, // SAFETY: The state is `Incomplete`. OnceExclusiveState::Incomplete => unsafe { really_init_mut(this) }, } @@ -258,7 +258,7 @@ impl T> LazyLock { // * the closure was not called, but a previous call initialized `value`. // * the closure was not called because the Once is poisoned, which we handled above. // So `value` has definitely been initialized and will not be modified again. - unsafe { &(*this.data.get()).value } + unsafe { LazyLock::get_unchecked(this) } } } @@ -286,7 +286,7 @@ impl LazyLock { match state { // SAFETY: // The closure has been run successfully, so `value` has been initialized. - OnceExclusiveState::Complete => Some(unsafe { &mut this.data.get_mut().value }), + OnceExclusiveState::Complete => Some(unsafe { LazyLock::get_unchecked_mut(this) }), _ => None, } } @@ -313,11 +313,71 @@ impl LazyLock { // SAFETY: // The closure has been run successfully, so `value` has been initialized // and will not be modified again. - Some(unsafe { &(*this.data.get()).value }) + Some(unsafe { LazyLock::get_unchecked(this) }) } else { None } } + + /// Returns a shared reference to the value stored in the `LazyLock` without + /// checking whether it has been initialized. + /// + /// # Safety + /// + /// The lazy value must be initialized before calling this function. + /// + /// # Examples + /// + /// ``` + /// #![feature(once_lazy_lock_get_unchecked)] + /// + /// use std::sync::LazyLock; + /// + /// let lazy = LazyLock::new(|| 42); + /// + /// // Initialize the lazy. + /// let _ = &*lazy; + /// + /// let value = unsafe { LazyLock::get_unchecked(&lazy) }; + /// assert_eq!(*value, 42); + /// ``` + #[inline] + #[unstable(feature = "once_lazy_lock_get_unchecked", issue = "162716")] + pub unsafe fn get_unchecked(this: &LazyLock) -> &T { + debug_assert!(this.once.is_completed()); + unsafe { &(*this.data.get()).value } + } + + /// Returns a mutable reference to the value stored in the `LazyLock` without + /// checking whether it has been initialized. + /// + /// # Safety + /// + /// The lazy value must be initialized before calling this function. + /// + /// # Examples + /// + /// ``` + /// #![feature(once_lazy_lock_get_unchecked)] + /// + /// use std::sync::LazyLock; + /// + /// let mut lazy = LazyLock::new(|| 42); + /// + /// // Initialize the lazy. + /// let _ = &*lazy; + /// + /// let value = unsafe { LazyLock::get_unchecked_mut(&mut lazy) }; + /// *value = 100; + /// + /// assert_eq!(*lazy, 100); + /// ``` + #[inline] + #[unstable(feature = "once_lazy_lock_get_unchecked", issue = "162716")] + pub unsafe fn get_unchecked_mut(this: &mut LazyLock) -> &mut T { + debug_assert!(this.once.is_completed()); + unsafe { &mut this.data.get_mut().value } + } } #[stable(feature = "lazy_cell", since = "1.80.0")] diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index 4b41fc4587829..e8e8f869dd038 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -585,20 +585,58 @@ impl OnceLock { res } + /// Returns a reference to the value in the `OnceLock` without checking + /// whether it has been initialized. + /// /// # Safety /// - /// The cell must be initialized + /// The `OnceLock` must be initialized before calling this function. + /// + /// # Examples + /// + /// ``` + /// #![feature(once_lazy_lock_get_unchecked)] + /// + /// use std::sync::OnceLock; + /// + /// let cell = OnceLock::new(); + /// cell.set(42).unwrap(); + /// + /// let value = unsafe { cell.get_unchecked() }; + /// assert_eq!(*value, 42); + /// ``` #[inline] - unsafe fn get_unchecked(&self) -> &T { + #[unstable(feature = "once_lazy_lock_get_unchecked", issue = "162716")] + pub unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.initialized()); unsafe { (&*self.value.get()).assume_init_ref() } } + /// Returns a mutable reference to the value in the `OnceLock` without + /// checking whether it has been initialized. + /// /// # Safety /// - /// The cell must be initialized + /// The `OnceLock` must be initialized before calling this function. + /// + /// # Examples + /// + /// ``` + /// #![feature(once_lazy_lock_get_unchecked)] + /// + /// use std::sync::OnceLock; + /// + /// let mut cell = OnceLock::new(); + /// cell.set(42).unwrap(); + /// + /// let value = unsafe { cell.get_unchecked_mut() }; + /// *value = 100; + /// + /// assert_eq!(*cell.get().unwrap(), 100); + /// ``` #[inline] - unsafe fn get_unchecked_mut(&mut self) -> &mut T { + #[unstable(feature = "once_lazy_lock_get_unchecked", issue = "162716")] + pub unsafe fn get_unchecked_mut(&mut self) -> &mut T { debug_assert!(self.initialized_mut()); unsafe { self.value.get_mut().assume_init_mut() } } From 51fa7ee7e393b35a296697ee58bace514e17a6da Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sat, 19 Sep 2026 20:49:22 +0000 Subject: [PATCH 589/745] also apply late discriminant comparison optimization to `derive(Ord)` --- .../rustc_builtin_macros/src/deriving/ord.rs | 35 +++++++++-- .../src/deriving/partial_ord.rs | 42 +++++++------ tests/ui/derives/deriving-all-codegen.stdout | 60 ++++++++----------- 3 files changed, 76 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/ord.rs b/compiler/rustc_builtin_macros/src/deriving/ord.rs index 426fa41a3b6d4..c6b37d8d0edea 100644 --- a/compiler/rustc_builtin_macros/src/deriving/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/ord.rs @@ -5,6 +5,7 @@ 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::path_std; pub(crate) fn expand_deriving_ord( @@ -14,6 +15,8 @@ pub(crate) fn expand_deriving_ord( push: &mut dyn FnMut(Box), is_const: bool, ) { + let discr_then_data = discr_data_order(item); + let trait_def = TraitDef { span, path: path_std!(cx, span, cmp::Ord), @@ -29,7 +32,12 @@ pub(crate) fn expand_deriving_ord( 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), + combine_substructure: combine_substructure(|cx, span, substr| cs_cmp( + cx, + span, + substr, + discr_then_data + )), }], associated_types: SmallVec::new(), is_const, @@ -40,7 +48,12 @@ pub(crate) fn expand_deriving_ord( trait_def.expand(cx, item, push) } -pub(crate) fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> BlockOrExpr { +pub(crate) fn cs_cmp( + cx: &ExtCtxt<'_>, + span: Span, + 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]); @@ -62,10 +75,20 @@ pub(crate) fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> let args = thin_vec![field.self_expr, other_expr]; cx.expr_call_global(field.span, cmp_path.clone(), args) }, - |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]) + |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()), ); diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index e176152c507c9..2f30aa7a5cc0e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -18,25 +18,7 @@ pub(crate) fn expand_deriving_partial_ord( 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 { - let dataful: Vec = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect(); - match dataful.iter().filter(|&&b| b).count() { - // No data, placing the discriminant check first makes codegen simpler - 0 => true, - 1..=2 => false, - _ => (0..dataful.len() - 1).any(|i| { - if dataful[i] - && let Some(idx) = dataful[i + 1..].iter().position(|v| *v) - { - idx >= 2 - } else { - false - } - }), - } - } else { - true - }; + let discr_then_data = discr_data_order(item); let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); let has_derive_ord = cx.resolver.has_derive_ord(container_id); @@ -95,6 +77,28 @@ pub(crate) fn expand_deriving_partial_ord( trait_def.expand_ext(cx, item, push, is_simple) } +pub(crate) fn discr_data_order(item: &ast::Item) -> bool { + if let ItemKind::Enum(_, _, def) = &item.kind { + let dataful: Vec = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect(); + match dataful.iter().filter(|&&b| b).count() { + // No data, placing the discriminant check first makes codegen simpler + 0 => true, + 1..=2 => false, + _ => (0..dataful.len() - 1).any(|i| { + if dataful[i] + && let Some(idx) = dataful[i + 1..].iter().position(|v| *v) + { + idx >= 2 + } else { + false + } + }), + } + } else { + true + } +} + // Special case for the type deriving both `PartialOrd` and `Ord`. Builds: // ``` // Some(::core::cmp::Ord::cmp(self, other)) diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index ddd1158132c7d..92d5030372518 100644 --- a/tests/ui/derives/deriving-all-codegen.stdout +++ b/tests/ui/derives/deriving-all-codegen.stdout @@ -1319,21 +1319,17 @@ impl ::core::cmp::Ord for Mixed { 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) { - ::core::cmp::Ordering::Equal => - match (self, other) { - (Mixed::R(__self_0), Mixed::R(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), - (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { - d1: __arg1_0, d2: __arg1_1 }) => - match ::core::cmp::Ord::cmp(__self_0, __arg1_0) { - ::core::cmp::Ordering::Equal => - ::core::cmp::Ord::cmp(__self_1, __arg1_1), - cmp => cmp, - }, - _ => ::core::cmp::Ordering::Equal, + match (self, other) { + (Mixed::R(__self_0), Mixed::R(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { + d1: __arg1_0, d2: __arg1_1 }) => + match ::core::cmp::Ord::cmp(__self_0, __arg1_0) { + ::core::cmp::Ordering::Equal => + ::core::cmp::Ord::cmp(__self_1, __arg1_1), + cmp => cmp, }, - cmp => cmp, + _ => ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr), } } } @@ -1501,18 +1497,14 @@ impl ::core::cmp::Ord for Fielded { 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) { - ::core::cmp::Ordering::Equal => - match (self, other) { - (Fielded::X(__self_0), Fielded::X(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), - (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), - (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), - _ => unsafe { ::core::intrinsics::unreachable() } - }, - cmp => cmp, + match (self, other) { + (Fielded::X(__self_0), Fielded::X(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => + ::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), } } } @@ -1624,16 +1616,12 @@ impl ::core::cmp::Ord for 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) { - ::core::cmp::Ordering::Equal => - 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), - _ => unsafe { ::core::intrinsics::unreachable() } - }, - cmp => cmp, + 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), } } } From 9b9cb70640a38e006a36b86e91975c6659802475 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Tue, 22 Sep 2026 16:44:04 -0400 Subject: [PATCH 590/745] Stop embedding device code, now that the clang-linker-wrapper isn't consuming it anymore --- compiler/rustc_codegen_llvm/src/back/write.rs | 16 +--------------- compiler/rustc_codegen_llvm/src/diagnostics.rs | 4 ---- .../rustc_codegen_llvm/src/llvm/offload_ffi.rs | 16 ---------------- .../llvm-wrapper/offload/OffloadWrapper.cpp | 17 ----------------- 4 files changed, 1 insertion(+), 52 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 92989ba2dcf46..fa11a6abe6ed2 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -824,9 +824,7 @@ pub(crate) unsafe fn llvm_optimize( // This assumes that we previously compiled our kernels for a gpu target, which created a // `device.bin` artifact. The user is supposed to provide us with a path to this artifact, we - // don't need any other artifacts from the previous run. We will embed this artifact into our - // LLVM-IR host module, to create a `host.o` ObjectFile, which we will write to disk. - // The last, not yet automated steps uses the `clang-linker-wrapper` to process `host.o`. + // don't need any other artifacts from the previous run. if !cgcx.target_is_like_gpu && is_final_stage { if let Some(device_path) = config .offload @@ -850,18 +848,6 @@ pub(crate) unsafe fn llvm_optimize( let out_obj = host_dir.join("host.o"); let device_bin_c = path_to_c_string(device_pathbuf.as_path()); - // 2) Finalize host: lib.bc + device.bin -> host.o (host TM) - // We create a full clone of our LLVM host module, since we will embed the device IR - // into it, and this might break caching or incremental compilation otherwise. - let ok = unsafe { - llvm::RustOffloadWrapper::get_instance().llvm_rust_offload_embed_buffer_in_module( - module.module_llvm.llmod(), - device_bin_c.as_c_str(), - ) - }; - if !ok { - dcx.emit_err(crate::diagnostics::OffloadEmbedFailed); - } write_output_file( dcx, module.module_llvm.tm.raw(), diff --git a/compiler/rustc_codegen_llvm/src/diagnostics.rs b/compiler/rustc_codegen_llvm/src/diagnostics.rs index 78e502f13af75..d589c157cb9f0 100644 --- a/compiler/rustc_codegen_llvm/src/diagnostics.rs +++ b/compiler/rustc_codegen_llvm/src/diagnostics.rs @@ -101,10 +101,6 @@ pub(crate) struct OffloadNonexistingPath; #[diag("call to BundleImages failed, `device.bin` was not created")] pub(crate) struct OffloadBundleImagesFailed; -#[derive(Diagnostic)] -#[diag("call to EmbedBufferInModule failed, `host.o` was not created")] -pub(crate) struct OffloadEmbedFailed; - #[derive(Diagnostic)] #[diag("call to WrapImages failed, device image was not wrapped into the host module")] pub(crate) struct OffloadWrapImagesFailed; diff --git a/compiler/rustc_codegen_llvm/src/llvm/offload_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/offload_ffi.rs index fecb9e40eab88..da3da6bd7abd4 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/offload_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/offload_ffi.rs @@ -5,7 +5,6 @@ use std::sync::OnceLock; use super::ffi::{Module, TargetMachine, Value}; type LLVMRustBundleImagesFn = unsafe extern "C" fn(&Module, &TargetMachine, *const c_char) -> bool; -type LLVMRustOffloadEmbedBufferInModuleFn = unsafe extern "C" fn(&Module, *const c_char) -> bool; type LLVMRustOffloadMapperFn = unsafe extern "C" fn(&Value, &Value, *const &Value); type LLVMRustOffloadWrapImagesFn = unsafe extern "C" fn(&Module, *const c_char, *const c_char) -> bool; @@ -18,7 +17,6 @@ use crate::llvm; pub(crate) struct RustOffloadWrapper { LLVMRustBundleImages: LLVMRustBundleImagesFn, - LLVMRustOffloadEmbedBufferInModule: LLVMRustOffloadEmbedBufferInModuleFn, LLVMRustOffloadMapper: LLVMRustOffloadMapperFn, LLVMRustOffloadWrapImages: LLVMRustOffloadWrapImagesFn, lld_path: Option, @@ -65,14 +63,6 @@ impl RustOffloadWrapper { unsafe { (self.LLVMRustBundleImages)(m, tm, c.as_ptr()) } } - pub(crate) unsafe fn llvm_rust_offload_embed_buffer_in_module( - &self, - m: &Module, - i: &CStr, - ) -> bool { - unsafe { (self.LLVMRustOffloadEmbedBufferInModule)(m, i.as_ptr()) } - } - pub(crate) unsafe fn llvm_rust_offload_wrapper(&self, v1: &Value, v2: &Value, vs: &[&Value]) { unsafe { (self.LLVMRustOffloadMapper)(v1, v2, vs.as_ptr()) } } @@ -96,11 +86,6 @@ impl RustOffloadWrapper { let llvm_rust_bundle_images = *unsafe { lib.get::(b"LLVMRustBundleImages\0")? }; - let llvm_rust_offload_embed_buffer_in_module = *unsafe { - lib.get::( - b"LLVMRustOffloadEmbedBufferInModule\0", - )? - }; let llvm_rust_offload_wrapper = *unsafe { lib.get::(b"LLVMRustOffloadMapper\0")? }; let llvm_rust_offload_wrap_images = @@ -108,7 +93,6 @@ impl RustOffloadWrapper { Ok(Self { LLVMRustBundleImages: llvm_rust_bundle_images, - LLVMRustOffloadEmbedBufferInModule: llvm_rust_offload_embed_buffer_in_module, LLVMRustOffloadMapper: llvm_rust_offload_wrapper, LLVMRustOffloadWrapImages: llvm_rust_offload_wrap_images, lld_path, diff --git a/compiler/rustc_llvm/llvm-wrapper/offload/OffloadWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/offload/OffloadWrapper.cpp index bed54da0a7045..ca4d181179ffd 100644 --- a/compiler/rustc_llvm/llvm-wrapper/offload/OffloadWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/offload/OffloadWrapper.cpp @@ -28,7 +28,6 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Transforms/Utils/ModuleUtils.h" #include "llvm/Transforms/Utils/ValueMapper.h" #include @@ -88,22 +87,6 @@ extern "C" bool LLVMRustBundleImages(LLVMModuleRef M, TargetMachine &TM, return true; } -extern "C" bool LLVMRustOffloadEmbedBufferInModule(LLVMModuleRef HostM, - const char *HostOutPath) { - auto MBOrErr = MemoryBuffer::getFile(HostOutPath); - if (!MBOrErr) { - auto E = MBOrErr.getError(); - auto _B = errorCodeToError(E); - return false; - } - MemoryBufferRef Buf = (*MBOrErr)->getMemBufferRef(); - Module *M = unwrap(HostM); - StringRef SectionName = ".llvm.offloading"; - Align Alignment = Align(8); - llvm::embedBufferInModule(*M, Buf, SectionName, Alignment); - return true; -} - // Clone OldFn into NewFn, remapping its arguments to RebuiltArgs. // Each arg of OldFn is replaced with the corresponding value in RebuiltArgs. // For scalars, RebuiltArgs contains the value cast and/or truncated to the From 3e068233b330c689c8360a01fff8c155f4c29598 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Sep 2026 22:31:35 +0200 Subject: [PATCH 591/745] add test for #[path] in doctest --- src/tools/miri/test-cargo-miri/src/doctest.rs | 4 ++++ src/tools/miri/test-cargo-miri/src/lib.rs | 7 +++++++ 2 files changed, 11 insertions(+) create mode 100644 src/tools/miri/test-cargo-miri/src/doctest.rs diff --git a/src/tools/miri/test-cargo-miri/src/doctest.rs b/src/tools/miri/test-cargo-miri/src/doctest.rs new file mode 100644 index 0000000000000..9e1dd68dc1a2b --- /dev/null +++ b/src/tools/miri/test-cargo-miri/src/doctest.rs @@ -0,0 +1,4 @@ +// Imported into a doctest via `#[path]`. +pub fn make_true() -> bool { + true +} diff --git a/src/tools/miri/test-cargo-miri/src/lib.rs b/src/tools/miri/test-cargo-miri/src/lib.rs index 3b63f8afc9023..0b268e6969d68 100644 --- a/src/tools/miri/test-cargo-miri/src/lib.rs +++ b/src/tools/miri/test-cargo-miri/src/lib.rs @@ -26,6 +26,13 @@ /// /// let _val = Fail::::C; /// ``` +/// +/// Doctest with `#[path]`: +/// +/// ```rust +/// #[path = "doctest.rs"] mod doctest; +/// assert!(doctest::make_true()); +/// ``` // This is imported in `main.rs`. #[unsafe(no_mangle)] pub fn make_true() -> bool { From 4f20be313591a2bd1404bd85676ce38895330c77 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Tue, 22 Sep 2026 16:50:51 -0400 Subject: [PATCH 592/745] also drop now unused host.o --- compiler/rustc_codegen_llvm/src/back/write.rs | 19 ------------------- .../offload/host-std-device-nostd/rmake.rs | 2 -- 2 files changed, 21 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index fa11a6abe6ed2..233e4a6b06612 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -843,26 +843,7 @@ pub(crate) unsafe fn llvm_optimize( } else if !device_pathbuf.exists() { dcx.emit_err(crate::diagnostics::OffloadNonexistingPath); } - let host_path = cgcx.output_filenames.path(OutputType::Object); - let host_dir = host_path.parent().unwrap(); - let out_obj = host_dir.join("host.o"); let device_bin_c = path_to_c_string(device_pathbuf.as_path()); - - write_output_file( - dcx, - module.module_llvm.tm.raw(), - config.no_builtins, - module.module_llvm.llmod(), - &out_obj, - None, - llvm::FileType::ObjectFile, - prof, - true, - ); - // We ignore cgcx.save_temps here and unconditionally always keep our `device.bin` artifact. - // Otherwise, recompiling the host code would fail since we deleted that device artifact - // in the previous host compilation, which would be confusing at best. - let ok = unsafe { llvm::RustOffloadWrapper::get_instance().llvm_rust_offload_wrap_images( module.module_llvm.llmod(), diff --git a/tests/run-make/offload/host-std-device-nostd/rmake.rs b/tests/run-make/offload/host-std-device-nostd/rmake.rs index 35f408e8b1cd0..6769993f9cf98 100644 --- a/tests/run-make/offload/host-std-device-nostd/rmake.rs +++ b/tests/run-make/offload/host-std-device-nostd/rmake.rs @@ -35,6 +35,4 @@ fn main() { .arg("-Clto=fat") .emit("obj") .run(); - - assert!(cwd().join("host.o").exists()); } From 7779f5cf60bf306f537d1d2fb6c57b7fdf33b7bb Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Tue, 22 Sep 2026 20:14:32 +0000 Subject: [PATCH 593/745] Test unused lifetime params for 'type' and 'union' --- tests/ui/variance/variance-unused-region-param.rs | 2 ++ tests/ui/variance/variance-unused-region-param.stderr | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/ui/variance/variance-unused-region-param.rs b/tests/ui/variance/variance-unused-region-param.rs index f0e4e03c9db8d..0ada6b4aa7907 100644 --- a/tests/ui/variance/variance-unused-region-param.rs +++ b/tests/ui/variance/variance-unused-region-param.rs @@ -2,6 +2,8 @@ struct SomeStruct<'a> { x: u32 } //~ ERROR parameter `'a` is never used enum SomeEnum<'a> { Nothing } //~ ERROR parameter `'a` is never used +union SomeUnion<'a> { x: u32 } //~ ERROR parameter `'a` is never used trait SomeTrait<'a> { fn foo(&self); } // OK on traits. +type SomeAlias<'a> = u32; // OK on type aliases. fn main() {} diff --git a/tests/ui/variance/variance-unused-region-param.stderr b/tests/ui/variance/variance-unused-region-param.stderr index b9c08bd43c454..b74cb977522d4 100644 --- a/tests/ui/variance/variance-unused-region-param.stderr +++ b/tests/ui/variance/variance-unused-region-param.stderr @@ -14,6 +14,14 @@ LL | enum SomeEnum<'a> { Nothing } | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` -error: aborting due to 2 previous errors +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/variance-unused-region-param.rs:5:17 + | +LL | union SomeUnion<'a> { x: u32 } + | ^^ unused lifetime parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0392`. From 4eb7bb33234293cbc0b4bebfc5e37e6eaffeddda Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Sun, 31 May 2026 13:56:23 +0200 Subject: [PATCH 594/745] core/alloc: stabilise `Allocator` --- compiler/rustc_data_structures/src/lib.rs | 3 +- compiler/rustc_middle/src/lib.rs | 3 +- library/alloc/src/alloc.rs | 16 +-- library/alloc/src/boxed.rs | 103 +++++++--------- library/alloc/src/boxed/thin.rs | 1 - .../alloc/src/collections/binary_heap/mod.rs | 33 +++--- library/alloc/src/collections/btree/map.rs | 17 ++- .../alloc/src/collections/btree/map/entry.rs | 8 +- library/alloc/src/collections/btree/set.rs | 22 ++-- .../alloc/src/collections/btree/set/entry.rs | 6 +- library/alloc/src/collections/linked_list.rs | 14 +-- .../alloc/src/collections/vec_deque/drain.rs | 2 +- .../src/collections/vec_deque/extract_if.rs | 4 +- .../src/collections/vec_deque/into_iter.rs | 2 +- .../alloc/src/collections/vec_deque/mod.rs | 12 +- .../alloc/src/collections/vec_deque/splice.rs | 2 +- library/alloc/src/lib.rs | 2 +- library/alloc/src/rc.rs | 105 ++++++++--------- library/alloc/src/slice.rs | 4 +- library/alloc/src/sync.rs | 111 +++++++++--------- library/alloc/src/vec/drain.rs | 4 +- library/alloc/src/vec/extract_if.rs | 4 +- library/alloc/src/vec/into_iter.rs | 4 +- library/alloc/src/vec/mod.rs | 48 +++----- library/alloc/src/vec/peek_mut.rs | 2 +- library/alloc/src/vec/splice.rs | 2 +- library/alloctests/lib.rs | 2 +- library/alloctests/tests/lib.rs | 2 +- .../alloctests/tests/vec_deque_alloc_error.rs | 2 +- library/core/src/alloc/mod.rs | 38 +++--- library/core/src/ptr/non_null.rs | 2 +- library/std/src/alloc.rs | 8 +- library/std/src/collections/hash/map.rs | 36 +++--- library/std/src/collections/hash/set.rs | 38 +++--- library/std/src/lib.rs | 2 +- .../{allocator-api.md => allocator-ext.md} | 2 +- src/tools/clippy/tests/ui/vec_box_sized.rs | 2 +- .../tests/fail/alloc/alloc_error_handler.rs | 2 +- .../fail/alloc/alloc_error_handler_custom.rs | 2 +- .../fail/alloc/alloc_error_handler_no_std.rs | 2 +- .../tests/fail/alloc/global_system_mixup.rs | 2 +- .../validity/box-custom-alloc-dangling-ptr.rs | 2 +- .../box-custom-alloc-invalid-alloc.rs | 2 +- .../tests/panic/alloc_error_handler_hook.rs | 2 +- .../tests/pass/box-custom-alloc-aliasing.rs | 1 - src/tools/miri/tests/pass/box-custom-alloc.rs | 1 - src/tools/miri/tests/pass/global_allocator.rs | 2 +- src/tools/miri/tests/pass/heap_allocator.rs | 2 +- tests/incremental/lint-unused-features.rs | 7 +- .../mir-opt/box_conditional_drop_allocator.rs | 2 +- .../issue_117368_print_invalid_constant.rs | 2 +- tests/run-make/std-core-cycle/bar.rs | 2 +- tests/ui/README.md | 2 +- tests/ui/allocator/156920-allocator-clone.rs | 2 +- tests/ui/allocator/157089-box-pin-in.rs | 2 +- tests/ui/allocator/159445-unsize-pin-box.rs | 2 +- tests/ui/allocator/alloc-shrink-oob-read.rs | 1 - tests/ui/allocator/auxiliary/custom.rs | 2 +- tests/ui/allocator/custom.rs | 1 - tests/ui/allocator/dyn-compatible.rs | 2 - tests/ui/allocator/xcrate-use.rs | 1 - tests/ui/array-slice-vec/vec-res-add.stderr | 1 + .../async-drop/async-drop-box-allocator.rs | 2 +- tests/ui/box/alloc-unstable-fail.rs | 6 - tests/ui/box/alloc-unstable-fail.stderr | 13 -- tests/ui/box/alloc-unstable.rs | 5 - tests/ui/box/issue-95036.rs | 2 +- tests/ui/box/large-allocator-ice.rs | 2 +- tests/ui/box/leak-alloc.rs | 2 +- .../impl-foreign-for-box[foreign_local].rs | 2 +- ...parison_instead_of_pattern_matching.stderr | 4 + .../debuginfo-box-with-large-allocator.rs | 2 +- .../ui/drop/box-conditional-drop-allocator.rs | 1 - .../could-not-resolve-issue-121503.rs | 2 +- tests/ui/lint/must_not_suspend/allocator.rs | 2 +- .../unused-features/used-library-features.rs | 4 +- tests/ui/lto/issue-100772.rs | 2 +- .../implicit-const-deref.stderr | 1 + tests/ui/pattern/issue-115599.stderr | 1 + tests/ui/pattern/pattern-tyvar-2.stderr | 1 + .../ui/precondition-checks/vec-from-parts.rs | 2 +- .../precondition-checks/vec-from-raw-parts.rs | 2 +- tests/ui/regions/regions-mock-codegen.rs | 1 - .../suggest-vec-allocator-api.rs | 9 -- .../suggest-vec-allocator-api.stderr | 53 --------- tests/ui/traits/const-traits/issue-102156.rs | 2 +- 86 files changed, 362 insertions(+), 478 deletions(-) rename src/doc/unstable-book/src/library-features/{allocator-api.md => allocator-ext.md} (96%) delete mode 100644 tests/ui/box/alloc-unstable-fail.rs delete mode 100644 tests/ui/box/alloc-unstable-fail.stderr delete mode 100644 tests/ui/box/alloc-unstable.rs delete mode 100644 tests/ui/stability-attribute/suggest-vec-allocator-api.rs delete mode 100644 tests/ui/stability-attribute/suggest-vec-allocator-api.stderr diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index ab30806bd2a59..041763f57fc9e 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,10 +10,11 @@ #![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(not(bootstrap), feature(allocator_ext))] #![cfg_attr(test, feature(test))] #![deny(unsafe_op_in_unsafe_fn)] -#![feature(allocator_api)] #![feature(ascii_char)] #![feature(ascii_char_variants)] #![feature(auto_traits)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 48d90f9c704fc..5acf9e150bb5c 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -27,9 +27,10 @@ // 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))] -#![feature(allocator_api)] +#![cfg_attr(not(bootstrap), feature(allocator_ext))] #![feature(associated_type_defaults)] #![feature(closure_track_caller)] #![feature(const_default)] diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index f921bc292568d..ccac980706571 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -51,17 +51,17 @@ unsafe extern "Rust" { /// /// Note: while this type is unstable, the functionality it provides can be /// accessed through the [free functions in `alloc`](self#functions). -#[unstable(feature = "allocator_api", issue = "32838")] +#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] #[derive(Copy, Debug)] #[derive_const(Clone, Default)] // the compiler needs to know when a Box uses the global allocator vs a custom one #[lang = "global_alloc_ty"] pub struct Global; -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl core::alloc::AllocatorClone for Global {} -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl core::alloc::StaticAllocator for Global {} /// Allocates memory with the global allocator. @@ -539,7 +539,7 @@ impl Global { } } -#[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 Global { #[inline] @@ -690,13 +690,13 @@ pub mod __alloc_error_handler { /// a type with an `#[unstable] A: Allocator = Global` parameter may be /// callable for `A != Global`. #[marker] -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[doc(hidden)] pub trait AllocatorNightly: Allocator {} -#[unstable(feature = "allocator_api", issue = "32838")] -#[unstable_feature_bound(allocator_api)] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] impl AllocatorNightly for A {} -#[unstable(feature = "allocator_api", issue = "32838")] +#[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 ce36a9324b119..38d30b8f4f9ad 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, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] A: Allocator = Global, >(Unique, A); /// Monomorphic function for allocating an uninit `Box`. @@ -371,12 +371,12 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// let five = Box::try_new(5)?; /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new(x: T) -> Result { Self::try_new_in(x, Global) @@ -388,7 +388,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// let mut five = Box::::try_new_uninit()?; /// // Deferred initialization: @@ -398,7 +398,7 @@ impl Box { /// assert_eq!(*five, 5); /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_uninit() -> Result>, AllocError> { Box::try_new_uninit_in(Global) @@ -413,7 +413,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// let zero = Box::::try_new_zeroed()?; /// let zero = unsafe { zero.assume_init() }; @@ -423,7 +423,7 @@ impl Box { /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_zeroed() -> Result>, AllocError> { Box::try_new_zeroed_in(Global) @@ -438,14 +438,12 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::System; /// /// let five = Box::new_in(5, System); /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub fn new_in(x: T, alloc: A) -> Self { @@ -463,14 +461,14 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::alloc::System; /// /// let five = Box::try_new_in(5, System)?; /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_in(x: T, alloc: A) -> Result { let mut boxed = Self::try_new_uninit_in(alloc)?; @@ -484,7 +482,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::alloc::System; /// @@ -495,7 +493,7 @@ impl Box { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[cfg(not(no_global_oom_handling))] #[must_use] pub fn new_uninit_in(alloc: A) -> Box, A> { @@ -514,7 +512,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::alloc::System; /// @@ -526,7 +524,7 @@ impl Box { /// assert_eq!(*five, 5); /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { let ptr = if T::IS_ZST { NonNull::dangling() @@ -547,7 +545,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::alloc::System; /// @@ -558,7 +556,7 @@ impl Box { /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[cfg(not(no_global_oom_handling))] #[must_use] pub fn new_zeroed_in(alloc: A) -> Box, A> { @@ -581,7 +579,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::alloc::System; /// @@ -593,7 +591,7 @@ impl Box { /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { let ptr = if T::IS_ZST { NonNull::dangling() @@ -616,13 +614,13 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::alloc::System; /// /// let x = Box::pin_in(1, System); /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[must_use] #[inline(always)] pub fn pin_in(x: T, alloc: A) -> Pin @@ -802,13 +800,12 @@ impl Box { /// /// ``` /// #![feature(clone_from_ref)] - /// #![feature(allocator_api)] /// /// let hello: Box = Box::try_clone_from_ref("hello")?; /// # Ok::<(), std::alloc::AllocError>(()) /// ``` #[unstable(feature = "clone_from_ref", issue = "149075")] - //#[unstable(feature = "allocator_api", issue = "32838")] + //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_clone_from_ref(src: &T) -> Result, AllocError> { Box::try_clone_from_ref_in(src, Global) @@ -824,7 +821,6 @@ impl Box { /// /// ``` /// #![feature(clone_from_ref)] - /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -832,7 +828,7 @@ impl Box { /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "clone_from_ref", issue = "149075")] - //#[unstable(feature = "allocator_api", issue = "32838")] + //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[must_use] #[inline] pub fn clone_from_ref_in(src: &T, alloc: A) -> Box { @@ -851,7 +847,6 @@ impl Box { /// /// ``` /// #![feature(clone_from_ref)] - /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -859,7 +854,7 @@ impl Box { /// # Ok::<(), std::alloc::AllocError>(()) /// ``` #[unstable(feature = "clone_from_ref", issue = "149075")] - //#[unstable(feature = "allocator_api", issue = "32838")] + //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_clone_from_ref_in(src: &T, alloc: A) -> Result, AllocError> { struct DeallocDropGuard<'a, A: Allocator>(Layout, &'a A, NonNull); @@ -947,7 +942,7 @@ impl Box<[T]> { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// let mut values = Box::<[u32]>::try_new_uninit_slice(3)?; /// // Deferred initialization: @@ -959,7 +954,7 @@ impl Box<[T]> { /// assert_eq!(*values, [1, 2, 3]); /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_uninit_slice(len: usize) -> Result]>, AllocError> { let ptr = if T::IS_ZST || len == 0 { @@ -987,7 +982,7 @@ impl Box<[T]> { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// let values = Box::<[u32]>::try_new_zeroed_slice(3)?; /// let values = unsafe { values.assume_init() }; @@ -997,7 +992,7 @@ impl Box<[T]> { /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_zeroed_slice(len: usize) -> Result]>, AllocError> { let ptr = if T::IS_ZST || len == 0 { @@ -1023,7 +1018,7 @@ impl Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::alloc::System; /// @@ -1037,7 +1032,7 @@ impl Box<[T], A> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[must_use] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { // SAFETY: `len` is exactly the capacity of this `RawVec`. @@ -1053,7 +1048,7 @@ impl Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::alloc::System; /// @@ -1065,7 +1060,7 @@ impl Box<[T], A> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[must_use] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { // SAFETY: `len` is exactly the capacity of this `RawVec`. @@ -1078,7 +1073,7 @@ impl Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::alloc::System; /// @@ -1092,7 +1087,7 @@ impl Box<[T], A> { /// assert_eq!(*values, [1, 2, 3]); /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_uninit_slice_in( len: usize, @@ -1123,7 +1118,7 @@ impl Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::alloc::System; /// @@ -1135,7 +1130,7 @@ impl Box<[T], A> { /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_zeroed_slice_in( len: usize, @@ -1544,8 +1539,6 @@ impl Box { /// Recreate a `Box` which was previously converted to a raw pointer /// using [`Box::into_raw_with_allocator`]: /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::System; /// /// let x = Box::new_in(5, System); @@ -1554,7 +1547,7 @@ impl Box { /// ``` /// Manually create a `Box` from scratch by using the system allocator: /// ``` - /// #![feature(allocator_api, slice_ptr_get)] + /// #![feature(slice_ptr_get)] /// /// use std::alloc::{Allocator, Layout, System}; /// @@ -1571,7 +1564,7 @@ impl Box { /// /// [memory layout]: self#memory-layout /// [considerations for unsafe code]: self#considerations-for-unsafe-code - #[unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { // SAFETY: Upheld by caller. @@ -1602,8 +1595,6 @@ impl Box { /// Recreate a `Box` which was previously converted to a `NonNull` pointer /// using [`Box::into_non_null_with_allocator`]: /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::System; /// /// let x = Box::new_in(5, System); @@ -1612,8 +1603,6 @@ impl Box { /// ``` /// Manually create a `Box` from scratch by using the system allocator: /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::{Allocator, Layout, System}; /// /// unsafe { @@ -1628,7 +1617,7 @@ impl Box { /// /// [memory layout]: self#memory-layout /// [considerations for unsafe code]: self#considerations-for-unsafe-code - #[unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn from_non_null_in(raw: NonNull, alloc: A) -> Self { // SAFETY: guaranteed by the caller. @@ -1655,8 +1644,6 @@ impl Box { /// Converting the raw pointer back into a `Box` with [`Box::from_raw_in`] /// for automatic cleanup: /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::System; /// /// let x = Box::new_in(String::from("Hello"), System); @@ -1666,8 +1653,6 @@ impl Box { /// Manual cleanup by explicitly running the destructor and deallocating /// the memory: /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::{Allocator, Layout, System}; /// use std::ptr::{self, NonNull}; /// @@ -1682,7 +1667,7 @@ impl Box { /// /// [memory layout]: self#memory-layout #[must_use = "losing the pointer will leak memory"] - #[unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] #[inline] pub const fn into_raw_with_allocator(b: Self) -> (*mut T, A) { @@ -1719,8 +1704,6 @@ impl Box { /// Converting the `NonNull` pointer back into a `Box` with /// [`Box::from_non_null_in`] for automatic cleanup: /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::System; /// /// let x = Box::new_in(String::from("Hello"), System); @@ -1730,8 +1713,6 @@ impl Box { /// Manual cleanup by explicitly running the destructor and deallocating /// the memory: /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::{Allocator, Layout, System}; /// /// let x = Box::new_in(String::from("Hello"), System); @@ -1744,7 +1725,7 @@ impl Box { /// /// [memory layout]: self#memory-layout #[must_use = "losing the pointer will leak memory"] - #[unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn into_non_null_with_allocator(b: Self) -> (NonNull, A) { let (ptr, alloc) = Box::into_raw_with_allocator(b); @@ -1890,7 +1871,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. - #[unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn allocator(b: &Self) -> &A { &b.1 @@ -2511,7 +2492,7 @@ impl Error for Box { } } -#[unstable(feature = "allocator_api", issue = "32838")] +#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] unsafe impl Allocator for Box { #[inline] fn allocate(&self, layout: Layout) -> Result, AllocError> { diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 7d08991659787..90bb2ef9b838c 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -78,7 +78,6 @@ impl ThinBox { /// # Examples /// /// ``` - /// #![feature(allocator_api)] /// #![feature(thin_box)] /// use std::boxed::ThinBox; /// diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 8d730a49182bd..f3698a997c925 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -273,7 +273,7 @@ use crate::vec::{self, Vec}; #[cfg_attr(not(test), rustc_diagnostic_item = "BinaryHeap")] pub struct BinaryHeap< T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { data: Vec, } @@ -289,7 +289,7 @@ pub struct BinaryHeap< pub struct PeekMut< 'a, T: 'a + Ord, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { heap: &'a mut BinaryHeap, // If a set_len + sift_down are required, this is Some. If a &mut T has not @@ -482,7 +482,7 @@ impl fmt::Debug for BinaryHeap { struct RebuildOnDrop< 'a, T: Ord, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { heap: &'a mut BinaryHeap, rebuild_from: usize, @@ -543,14 +543,15 @@ impl BinaryHeap { /// Basic usage: /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::alloc::System; /// use std::collections::BinaryHeap; /// /// let heap : BinaryHeap = BinaryHeap::new_in(System); /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + #[rustc_const_unstable(feature = "allocator_ext", issue = "163177")] #[must_use] pub const fn new_in(alloc: A) -> BinaryHeap { BinaryHeap { data: Vec::new_in(alloc) } @@ -567,14 +568,14 @@ impl BinaryHeap { /// Basic usage: /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::alloc::System; /// use std::collections::BinaryHeap; /// /// let heap: BinaryHeap = BinaryHeap::with_capacity_in(10, System); /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[must_use] pub fn with_capacity_in(capacity: usize, alloc: A) -> BinaryHeap { BinaryHeap { data: Vec::with_capacity_in(capacity, alloc) } @@ -1417,7 +1418,7 @@ impl BinaryHeap { } /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn allocator(&self) -> &A { self.data.allocator() @@ -1692,14 +1693,14 @@ impl FusedIterator for Iter<'_, T> {} #[derive(Clone)] pub struct IntoIter< T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { iter: vec::IntoIter, } impl IntoIter { /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn allocator(&self) -> &A { self.iter.allocator() } @@ -1797,14 +1798,14 @@ unsafe impl AsVecIntoIter for IntoIter { #[derive(Clone, Debug)] pub struct IntoIterSorted< T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { inner: BinaryHeap, } impl IntoIterSorted { /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn allocator(&self) -> &A { self.inner.allocator() } @@ -1846,14 +1847,14 @@ unsafe impl TrustedLen for IntoIterSorted {} pub struct Drain< 'a, T: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { iter: vec::Drain<'a, T, A>, } impl Drain<'_, T, A> { /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn allocator(&self) -> &A { self.iter.allocator() } @@ -1903,14 +1904,14 @@ impl FusedIterator for Drain<'_, T, A> {} pub struct DrainSorted< 'a, T: Ord, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { inner: &'a mut BinaryHeap, } impl<'a, T: Ord, A: Allocator> DrainSorted<'a, T, A> { /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn allocator(&self) -> &A { self.inner.allocator() } diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index e8ee6fa628bfa..6b74024613dee 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -189,7 +189,7 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; pub struct BTreeMap< K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { root: Option>, length: usize, @@ -446,7 +446,7 @@ impl<'a, K: 'a, V: 'a> Default for IterMut<'a, K, V> { pub struct IntoIter< K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { range: LazyLeafRange, length: usize, @@ -554,7 +554,7 @@ impl fmt::Debug for ValuesMut<'_, K, V> { pub struct IntoKeys< K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { inner: IntoIter, } @@ -577,7 +577,7 @@ impl fmt::Debug for IntoKeys { pub struct IntoValues< K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { inner: IntoIter, } @@ -684,7 +684,6 @@ impl BTreeMap { /// # Examples /// /// ``` - /// # #![feature(allocator_api)] /// # #![feature(btreemap_alloc)] /// /// use std::collections::BTreeMap; @@ -692,7 +691,7 @@ impl BTreeMap { /// /// let map: BTreeMap = BTreeMap::new_in(Global); /// ``` - #[unstable(feature = "btreemap_alloc", issue = "32838")] + #[unstable(feature = "btreemap_alloc", issue = "163177")] #[must_use] pub const fn new_in(alloc: A) -> BTreeMap { BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(alloc), _marker: PhantomData } @@ -2143,7 +2142,7 @@ pub struct ExtractIf< V, R, F, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { pred: F, inner: ExtractIfInner<'a, K, V, R>, @@ -3152,7 +3151,7 @@ pub struct CursorMut< 'a, K: 'a, V: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A = Global, > { inner: CursorMutKey<'a, K, V, A>, } @@ -3190,7 +3189,7 @@ pub struct CursorMutKey< 'a, K: 'a, V: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A = Global, > { // If current is None then it means the tree has not been allocated yet. current: Option, K, V, marker::Leaf>, marker::Edge>>, diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index d3a9651799ab8..3d5b4cf2b46f1 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -20,7 +20,7 @@ pub enum Entry< 'a, K: 'a, V: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { /// A vacant entry. #[stable(feature = "rust1", since = "1.0.0")] @@ -48,7 +48,7 @@ pub struct VacantEntry< 'a, K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { pub(super) key: K, /// `None` for a (empty) map without root @@ -76,7 +76,7 @@ pub struct OccupiedEntry< 'a, K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { pub(super) handle: Handle, K, V, marker::LeafOrInternal>, marker::KV>, pub(super) dormant_map: DormantMutRef<'a, BTreeMap>, @@ -104,7 +104,7 @@ pub struct OccupiedError< 'a, K: 'a, V: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { /// The entry in the map that was already occupied. pub entry: OccupiedEntry<'a, K, V, A>, diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 3b15bda185d9d..2a17b0b4c43f9 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -77,7 +77,7 @@ pub use self::entry::{Entry, OccupiedEntry, VacantEntry}; #[cfg_attr(not(test), rustc_diagnostic_item = "BTreeSet")] pub struct BTreeSet< T, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { map: BTreeMap, } @@ -153,7 +153,7 @@ impl fmt::Debug for Iter<'_, T> { #[derive(Debug)] pub struct IntoIter< T, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { iter: super::map::IntoIter, } @@ -183,7 +183,7 @@ pub struct Range<'a, T: 'a> { pub struct Difference< 'a, T: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { inner: DifferenceInner<'a, T, A>, } @@ -257,7 +257,7 @@ impl fmt::Debug for SymmetricDifference<'_, T> { pub struct Intersection< 'a, T: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { inner: IntersectionInner<'a, T, A>, } @@ -353,7 +353,6 @@ impl BTreeSet { /// /// ``` /// # #![allow(unused_mut)] - /// # #![feature(allocator_api)] /// # #![feature(btreemap_alloc)] /// /// use std::collections::BTreeSet; @@ -361,7 +360,7 @@ impl BTreeSet { /// /// let set: BTreeSet = BTreeSet::new_in(Global); /// ``` - #[unstable(feature = "btreemap_alloc", issue = "32838")] + #[unstable(feature = "btreemap_alloc", issue = "163177")] #[must_use] pub const fn new_in(alloc: A) -> BTreeSet { BTreeSet { map: BTreeMap::new_in(alloc) } @@ -1559,7 +1558,7 @@ pub struct ExtractIf< T, R, F, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { pred: F, inner: super::map::ExtractIfInner<'a, T, SetValZST, R>, @@ -2156,8 +2155,11 @@ impl Debug for Cursor<'_, K> { /// A `CursorMut` is created with the [`BTreeSet::lower_bound_mut`] and [`BTreeSet::upper_bound_mut`] /// methods. #[unstable(feature = "btree_cursors", issue = "107540")] -pub struct CursorMut<'a, K: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A = Global> -{ +pub struct CursorMut< + 'a, + K: 'a, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A = Global, +> { inner: super::map::CursorMut<'a, K, SetValZST, A>, } @@ -2193,7 +2195,7 @@ impl Debug for CursorMut<'_, K, A> { pub struct CursorMutKey< 'a, K: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A = Global, > { inner: super::map::CursorMutKey<'a, K, SetValZST, A>, } diff --git a/library/alloc/src/collections/btree/set/entry.rs b/library/alloc/src/collections/btree/set/entry.rs index 89bc09bca2f5c..71978c6e2168d 100644 --- a/library/alloc/src/collections/btree/set/entry.rs +++ b/library/alloc/src/collections/btree/set/entry.rs @@ -42,7 +42,7 @@ use crate::alloc::{AllocatorClone, Global}; pub enum Entry< 'a, T, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { /// An occupied entry. /// @@ -133,7 +133,7 @@ impl Debug for Entry<'_, T, A> { pub struct OccupiedEntry< 'a, T, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { pub(super) inner: map::OccupiedEntry<'a, T, SetValZST, A>, } @@ -175,7 +175,7 @@ impl Debug for OccupiedEntry<'_, T, A> { pub struct VacantEntry< 'a, T, - #[unstable(feature = "allocator_api", issue = "32838")] A: AllocatorClone = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: AllocatorClone = Global, > { pub(super) inner: map::VacantEntry<'a, T, SetValZST, A>, } diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 872b5e0d7682d..3acf4e6b18e16 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -50,7 +50,7 @@ mod tests; #[rustc_insignificant_dtor] pub struct LinkedList< T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { head: Option>>, tail: Option>>, @@ -141,7 +141,7 @@ impl fmt::Debug for IterMut<'_, T> { #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter< T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { list: LinkedList, } @@ -515,7 +515,7 @@ impl LinkedList { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::alloc::System; /// use std::collections::LinkedList; @@ -523,7 +523,7 @@ impl LinkedList { /// let list: LinkedList = LinkedList::new_in(System); /// ``` #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub const fn new_in(alloc: A) -> Self { LinkedList { head: None, tail: None, len: 0, alloc, marker: PhantomData } } @@ -1365,7 +1365,7 @@ impl Default for IterMut<'_, T> { pub struct Cursor< 'a, T: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { index: usize, current: Option>>, @@ -1401,7 +1401,7 @@ impl fmt::Debug for Cursor<'_, T, A> { pub struct CursorMut< 'a, T: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { index: usize, current: Option>>, @@ -2000,7 +2000,7 @@ pub struct ExtractIf< 'a, T: 'a, F: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { list: &'a mut LinkedList, it: Option>>, diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index b56af5f0e85b6..38d540ab08040 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -18,7 +18,7 @@ use crate::alloc::{Allocator, Global}; pub struct Drain< 'a, T: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { // We can't just use a &mut VecDeque, as that would make Drain invariant over T // and we want it to be covariant instead diff --git a/library/alloc/src/collections/vec_deque/extract_if.rs b/library/alloc/src/collections/vec_deque/extract_if.rs index 61a75cadf4a26..4e74b0b84cb54 100644 --- a/library/alloc/src/collections/vec_deque/extract_if.rs +++ b/library/alloc/src/collections/vec_deque/extract_if.rs @@ -27,7 +27,7 @@ pub struct ExtractIf< 'a, T, F, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { vec: &'a mut VecDeque, /// The index of the item that will be inspected by the next call to `next`. @@ -57,7 +57,7 @@ impl<'a, T, F, A: Allocator> ExtractIf<'a, T, F, A> { } /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn allocator(&self) -> &A { self.vec.allocator() diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs index e18b85dd4b694..7cac57421ac5e 100644 --- a/library/alloc/src/collections/vec_deque/into_iter.rs +++ b/library/alloc/src/collections/vec_deque/into_iter.rs @@ -18,7 +18,7 @@ use crate::alloc::{Allocator, Global}; #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter< T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { inner: VecDeque, } diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index e068add469f3b..8e4507c6fd0aa 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -103,7 +103,7 @@ mod tests; #[rustc_insignificant_dtor] pub struct VecDeque< T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { // `self[0]`, if it exists, is `buf[head]`. // `head < buf.capacity()`, unless `buf.capacity() == 0` when `head == 0`. @@ -904,7 +904,7 @@ impl VecDeque { /// # Examples /// /// ``` - /// # #![feature(allocator_api)] + /// # #![feature(allocator_ext)] /// /// use std::collections::VecDeque; /// use std::alloc::Global; @@ -912,7 +912,7 @@ impl VecDeque { /// let deque: VecDeque = VecDeque::new_in(Global); /// ``` #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub const fn new_in(alloc: A) -> VecDeque { VecDeque { head: WrappedIndex::zero(), len: 0, buf: RawVec::new_in(alloc) } } @@ -922,14 +922,14 @@ impl VecDeque { /// # Examples /// /// ``` - /// # #![feature(allocator_api)] + /// # #![feature(allocator_ext)] /// /// use std::collections::VecDeque; /// use std::alloc::Global; /// /// let deque: VecDeque = VecDeque::with_capacity_in(10, Global); /// ``` - #[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) -> VecDeque { VecDeque { head: WrappedIndex::zero(), @@ -1648,7 +1648,7 @@ impl VecDeque { } /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn allocator(&self) -> &A { self.buf.allocator() diff --git a/library/alloc/src/collections/vec_deque/splice.rs b/library/alloc/src/collections/vec_deque/splice.rs index 93e5a0b4addf0..b1fd67df3d2d7 100644 --- a/library/alloc/src/collections/vec_deque/splice.rs +++ b/library/alloc/src/collections/vec_deque/splice.rs @@ -24,7 +24,7 @@ use crate::vec::Vec; pub struct Splice< 'a, I: Iterator + 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator + 'a = Global, > { pub(super) drain: Drain<'a, I::Item, A>, pub(super) replace_with: I, diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 664e3a4b1e218..de6830a514656 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -89,7 +89,7 @@ // // Library features: // tidy-alphabetical-start -#![feature(allocator_api)] +#![feature(allocator_ext)] #![feature(array_into_iter_constructors)] #![feature(ascii_char)] #![feature(async_fn_traits)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 229de8337d94b..0571f50b8a23b 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -323,7 +323,7 @@ fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout { pub struct Rc< T: ?Sized, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { ptr: NonNull>, phantom: PhantomData>, @@ -566,13 +566,13 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::rc::Rc; /// /// let five = Rc::try_new(5); /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn try_new(value: T) -> Result, AllocError> { // SAFETY: There is an implicit weak pointer owned by all the strong // pointers, which ensures that the weak destructor never frees @@ -592,7 +592,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::rc::Rc; /// @@ -606,7 +606,7 @@ impl Rc { /// assert_eq!(*five, 5); /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn try_new_uninit() -> Result>, AllocError> { // ignore-tidy-undocumented-unsafe unsafe { @@ -627,7 +627,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::rc::Rc; /// @@ -639,7 +639,7 @@ impl Rc { /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn try_new_zeroed() -> Result>, AllocError> { // ignore-tidy-undocumented-unsafe unsafe { @@ -667,7 +667,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::rc::Rc; /// use std::alloc::System; @@ -675,7 +675,7 @@ impl Rc { /// let five = Rc::new_in(5, System); /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn new_in(value: T, alloc: A) -> Rc { // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. @@ -692,7 +692,7 @@ impl Rc { /// /// ``` /// #![feature(get_mut_unchecked)] - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::rc::Rc; /// use std::alloc::System; @@ -709,7 +709,7 @@ impl Rc { /// assert_eq!(*five, 5) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn new_uninit_in(alloc: A) -> Rc, A> { // ignore-tidy-undocumented-unsafe @@ -734,7 +734,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::rc::Rc; /// use std::alloc::System; @@ -747,7 +747,7 @@ impl Rc { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn new_zeroed_in(alloc: A) -> Rc, A> { // ignore-tidy-undocumented-unsafe @@ -793,7 +793,7 @@ impl Rc { /// [`new_cyclic`]: Rc::new_cyclic /// [`upgrade`]: Weak::upgrade #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn new_cyclic_in(data_fn: F, alloc: A) -> Rc where F: FnOnce(&Weak) -> T, @@ -845,14 +845,14 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::rc::Rc; /// use std::alloc::System; /// /// let five = Rc::try_new_in(5, System); /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_in(value: T, alloc: A) -> Result { // There is an implicit weak pointer owned by all the strong @@ -873,7 +873,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -891,7 +891,7 @@ impl Rc { /// assert_eq!(*five, 5); /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { // ignore-tidy-undocumented-unsafe @@ -917,7 +917,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::rc::Rc; /// use std::alloc::System; @@ -930,7 +930,7 @@ impl Rc { /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { // ignore-tidy-undocumented-unsafe @@ -949,7 +949,7 @@ impl Rc { /// Constructs a new `Pin>` in the provided allocator. If `T` does not implement `Unpin`, then /// `value` will be pinned in memory and unable to be moved. #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn pin_in(value: T, alloc: A) -> Pin where @@ -1204,7 +1204,7 @@ impl Rc<[T], A> { /// /// ``` /// #![feature(get_mut_unchecked)] - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::rc::Rc; /// use std::alloc::System; @@ -1223,7 +1223,7 @@ impl Rc<[T], A> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Rc<[mem::MaybeUninit], A> { // ignore-tidy-undocumented-unsafe @@ -1239,7 +1239,7 @@ impl Rc<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::rc::Rc; /// use std::alloc::System; @@ -1252,7 +1252,7 @@ impl Rc<[T], A> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Rc<[mem::MaybeUninit], A> { // ignore-tidy-undocumented-unsafe @@ -1361,14 +1361,13 @@ impl Rc { /// /// ``` /// #![feature(clone_from_ref)] - /// #![feature(allocator_api)] /// use std::rc::Rc; /// /// let hello: Rc = Rc::try_clone_from_ref("hello")?; /// # Ok::<(), std::alloc::AllocError>(()) /// ``` #[unstable(feature = "clone_from_ref", issue = "149075")] - //#[unstable(feature = "allocator_api", issue = "32838")] + //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn try_clone_from_ref(value: &T) -> Result, AllocError> { Rc::try_clone_from_ref_in(value, Global) } @@ -1381,7 +1380,7 @@ impl Rc { /// /// ``` /// #![feature(clone_from_ref)] - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::rc::Rc; /// use std::alloc::System; /// @@ -1389,7 +1388,7 @@ impl Rc { /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "clone_from_ref", issue = "149075")] - //#[unstable(feature = "allocator_api", issue = "32838")] + //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn clone_from_ref_in(value: &T, alloc: A) -> Rc { // `in_progress` drops the allocation if we panic before finishing initializing it. let mut in_progress: UniqueRcUninit = UniqueRcUninit::new(value, alloc); @@ -1410,7 +1409,7 @@ impl Rc { /// /// ``` /// #![feature(clone_from_ref)] - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::rc::Rc; /// use std::alloc::System; /// @@ -1418,7 +1417,7 @@ impl Rc { /// # Ok::<(), std::alloc::AllocError>(()) /// ``` #[unstable(feature = "clone_from_ref", issue = "149075")] - //#[unstable(feature = "allocator_api", issue = "32838")] + //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn try_clone_from_ref_in(value: &T, alloc: A) -> Result, AllocError> { // `in_progress` drops the allocation if we panic before finishing initializing it. let mut in_progress: UniqueRcUninit = UniqueRcUninit::try_new(value, alloc)?; @@ -1696,7 +1695,7 @@ impl Rc { /// to call it as `Rc::allocator(&r)` instead of `r.allocator()`. This /// is so that there is no conflict with a method on the inner type. #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn allocator(this: &Self) -> &A { &this.alloc } @@ -1709,7 +1708,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::rc::Rc; /// use std::alloc::System; /// @@ -1720,7 +1719,7 @@ impl Rc { /// assert_eq!(&*x, "hello"); /// ``` #[must_use = "losing the pointer will leak memory"] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { let this = mem::ManuallyDrop::new(this); let ptr = Self::as_ptr(&this); @@ -1791,7 +1790,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::rc::Rc; /// use std::alloc::System; @@ -1813,7 +1812,7 @@ impl Rc { /// Convert a slice back into its original array: /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::rc::Rc; /// use std::alloc::System; @@ -1826,7 +1825,7 @@ impl Rc { /// assert_eq!(&*x, &[1, 2, 3]); /// } /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { // ignore-tidy-undocumented-unsafe let offset = unsafe { data_offset(ptr) }; @@ -1915,7 +1914,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::rc::Rc; /// use std::alloc::System; @@ -1933,7 +1932,7 @@ impl Rc { /// } /// ``` #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub unsafe fn increment_strong_count_in(ptr: *const T, alloc: A) where A: AllocatorClone, @@ -1962,7 +1961,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::rc::Rc; /// use std::alloc::System; @@ -1980,7 +1979,7 @@ impl Rc { /// } /// ``` #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub unsafe fn decrement_strong_count_in(ptr: *const T, alloc: A) { // SAFETY: Upheld by caller. unsafe { drop(Rc::from_raw_in(ptr, alloc)) }; @@ -3304,7 +3303,7 @@ impl> ToRcSlice for I { #[rustc_diagnostic_item = "RcWeak"] pub struct Weak< T: ?Sized, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { // This is a `NonNull` to allow optimizing the size of this type in enums, // but it is not necessarily a valid pointer. @@ -3369,7 +3368,7 @@ impl Weak { /// assert!(empty.upgrade().is_none()); /// ``` #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn new_in(alloc: A) -> Weak { Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc } } @@ -3473,7 +3472,7 @@ impl Weak { impl Weak { /// Returns a reference to the underlying allocator. #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn allocator(&self) -> &A { &self.alloc } @@ -3532,7 +3531,7 @@ impl Weak { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::rc::{Rc, Weak}; /// use std::alloc::System; /// @@ -3551,7 +3550,7 @@ impl Weak { /// [`as_ptr`]: Weak::as_ptr #[must_use = "losing the pointer will leak memory"] #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn into_raw_with_allocator(self) -> (*const T, A) { let this = mem::ManuallyDrop::new(self); let result = this.as_ptr(); @@ -3603,7 +3602,7 @@ impl Weak { /// [`upgrade`]: Weak::upgrade /// [`new`]: Weak::new #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { // See Weak::as_ptr for context on how the input pointer is derived. @@ -4039,7 +4038,7 @@ fn data_offset_alignment(alignment: Alignment) -> usize { #[unstable(feature = "unique_rc_arc", issue = "112566")] pub struct UniqueRc< T: ?Sized, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { ptr: NonNull>, // Define the ownership of `RcInner` for drop-check @@ -4337,7 +4336,7 @@ impl UniqueRc { /// point to the new [`Rc`]. #[cfg(not(no_global_oom_handling))] #[unstable(feature = "unique_rc_arc", issue = "112566")] - // #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "allocator_api", issue = "163177")] #[must_use] pub fn new_in(value: T, alloc: A) -> Self { let (ptr, alloc) = Box::into_non_null_with_allocator(Box::new_in( @@ -4356,7 +4355,7 @@ impl UniqueRc { /// 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")] + // #[unstable(feature = "allocator_api", issue = "163177")] pub fn try_new_in(value: T, alloc: A) -> Result { let (ptr, alloc) = Box::into_non_null_with_allocator(Box::try_new_in( RcInner { @@ -4373,7 +4372,7 @@ impl UniqueRc { /// Consumes the `UniqueRc`, returning its wrapped value and allocator. #[unstable(feature = "unique_rc_arc", issue = "112566")] - // #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "allocator_api", issue = "163177")] #[must_use] pub fn unwrap_with_allocator(this: Self) -> (T, A) { let inner_ptr = this.ptr; @@ -4742,7 +4741,7 @@ impl Drop for UniqueRcUninit { } } -#[unstable(feature = "allocator_api", issue = "32838")] +#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] unsafe impl Allocator for Rc { #[inline] fn allocate(&self, layout: Layout) -> Result, AllocError> { @@ -4794,5 +4793,5 @@ unsafe impl Allocator for Rc { } } -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl AllocatorClone for Rc {} diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 4741fe12ae89c..438549160a1c6 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -381,7 +381,7 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::alloc::System; /// @@ -392,7 +392,7 @@ impl [T] { #[cfg(not(no_global_oom_handling))] #[rustc_allow_incoherent_impl] #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn to_vec_in(&self, alloc: A) -> Vec where T: Clone, diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index c71544925bef7..13e70a436234c 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -273,7 +273,7 @@ macro_rules! acquire { )] pub struct Arc< T: ?Sized, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { ptr: NonNull>, phantom: PhantomData>, @@ -359,7 +359,7 @@ impl Arc { #[rustc_diagnostic_item = "ArcWeak"] pub struct Weak< T: ?Sized, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { // This is a `NonNull` to allow optimizing the size of this type in enums, // but it is not necessarily a valid pointer. @@ -589,7 +589,7 @@ impl Arc { } /// Constructs a new `Pin>`, return an error if allocation fails. - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_pin(data: T) -> Result>, AllocError> { // SAFETY: We own and create the pinned pointer. @@ -601,13 +601,13 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::sync::Arc; /// /// let five = Arc::try_new(5)?; /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new(data: T) -> Result, AllocError> { // Start the weak pointer count as 1 which is the weak pointer that's @@ -627,7 +627,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::sync::Arc; /// @@ -641,7 +641,7 @@ impl Arc { /// assert_eq!(*five, 5); /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn try_new_uninit() -> Result>, AllocError> { // ignore-tidy-undocumented-unsafe unsafe { @@ -662,7 +662,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature( allocator_api)] + /// #![feature( allocator_ext)] /// /// use std::sync::Arc; /// @@ -674,7 +674,7 @@ impl Arc { /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn try_new_zeroed() -> Result>, AllocError> { // ignore-tidy-undocumented-unsafe unsafe { @@ -693,7 +693,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -702,7 +702,7 @@ impl Arc { /// ``` #[inline] #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn new_in(data: T, alloc: A) -> Arc { // Start the weak pointer count as 1 which is the weak pointer that's // held by all the strong pointers (kinda), see std/rc.rs for more info @@ -725,7 +725,7 @@ impl Arc { /// /// ``` /// #![feature(get_mut_unchecked)] - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -742,7 +742,7 @@ impl Arc { /// assert_eq!(*five, 5) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn new_uninit_in(alloc: A) -> Arc, A> { // ignore-tidy-undocumented-unsafe @@ -767,7 +767,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -780,7 +780,7 @@ impl Arc { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn new_zeroed_in(alloc: A) -> Arc, A> { // ignore-tidy-undocumented-unsafe @@ -827,7 +827,7 @@ impl Arc { /// [`upgrade`]: Weak::upgrade #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn new_cyclic_in(data_fn: F, alloc: A) -> Arc where F: FnOnce(&Weak) -> T, @@ -889,7 +889,7 @@ impl Arc { /// Constructs a new `Pin>` in the provided allocator. If `T` does not implement `Unpin`, /// then `data` will be pinned in memory and unable to be moved. #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn pin_in(data: T, alloc: A) -> Pin> where @@ -902,7 +902,7 @@ impl Arc { /// Constructs a new `Pin>` in the provided allocator, return an error if allocation /// fails. #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn try_pin_in(data: T, alloc: A) -> Result>, AllocError> where A: 'static, @@ -916,7 +916,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -924,7 +924,7 @@ impl Arc { /// let five = Arc::try_new_in(5, System)?; /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_in(data: T, alloc: A) -> Result, AllocError> { // Start the weak pointer count as 1 which is the weak pointer that's @@ -948,7 +948,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -966,7 +966,7 @@ impl Arc { /// assert_eq!(*five, 5); /// # Ok::<(), std::alloc::AllocError>(()) /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { // ignore-tidy-undocumented-unsafe @@ -992,7 +992,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -1005,7 +1005,7 @@ impl Arc { /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { // ignore-tidy-undocumented-unsafe @@ -1371,7 +1371,7 @@ impl Arc<[T], A> { /// /// ``` /// #![feature(get_mut_unchecked)] - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -1390,7 +1390,7 @@ impl Arc<[T], A> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { // ignore-tidy-undocumented-unsafe @@ -1406,7 +1406,7 @@ impl Arc<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -1419,7 +1419,7 @@ impl Arc<[T], A> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { // ignore-tidy-undocumented-unsafe @@ -1529,14 +1529,13 @@ impl Arc { /// /// ``` /// #![feature(clone_from_ref)] - /// #![feature(allocator_api)] /// use std::sync::Arc; /// /// let hello: Arc = Arc::try_clone_from_ref("hello")?; /// # Ok::<(), std::alloc::AllocError>(()) /// ``` #[unstable(feature = "clone_from_ref", issue = "149075")] - //#[unstable(feature = "allocator_api", issue = "32838")] + //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn try_clone_from_ref(value: &T) -> Result, AllocError> { Arc::try_clone_from_ref_in(value, Global) } @@ -1549,7 +1548,7 @@ impl Arc { /// /// ``` /// #![feature(clone_from_ref)] - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::sync::Arc; /// use std::alloc::System; /// @@ -1557,7 +1556,7 @@ impl Arc { /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "clone_from_ref", issue = "149075")] - //#[unstable(feature = "allocator_api", issue = "32838")] + //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn clone_from_ref_in(value: &T, alloc: A) -> Arc { // `in_progress` drops the allocation if we panic before finishing initializing it. let mut in_progress: UniqueArcUninit = UniqueArcUninit::new(value, alloc); @@ -1578,7 +1577,7 @@ impl Arc { /// /// ``` /// #![feature(clone_from_ref)] - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::sync::Arc; /// use std::alloc::System; /// @@ -1586,7 +1585,7 @@ impl Arc { /// # Ok::<(), std::alloc::AllocError>(()) /// ``` #[unstable(feature = "clone_from_ref", issue = "149075")] - //#[unstable(feature = "allocator_api", issue = "32838")] + //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn try_clone_from_ref_in(value: &T, alloc: A) -> Result, AllocError> { // `in_progress` drops the allocation if we panic before finishing initializing it. let mut in_progress: UniqueArcUninit = UniqueArcUninit::try_new(value, alloc)?; @@ -1880,7 +1879,7 @@ impl Arc { /// to call it as `Arc::allocator(&a)` instead of `a.allocator()`. This /// is so that there is no conflict with a method on the inner type. #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn allocator(this: &Self) -> &A { &this.alloc } @@ -1893,7 +1892,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::sync::Arc; /// use std::alloc::System; /// @@ -1904,7 +1903,7 @@ impl Arc { /// assert_eq!(&*x, "hello"); /// ``` #[must_use = "losing the pointer will leak memory"] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { let this = mem::ManuallyDrop::new(this); let ptr = Self::as_ptr(&this); @@ -1976,7 +1975,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -1998,7 +1997,7 @@ impl Arc { /// Convert a slice back into its original array: /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -2012,7 +2011,7 @@ impl Arc { /// } /// ``` #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { // SAFETY: Upheld by caller. unsafe { @@ -2150,7 +2149,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -2170,7 +2169,7 @@ impl Arc { /// } /// ``` #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub unsafe fn increment_strong_count_in(ptr: *const T, alloc: A) where A: AllocatorClone, @@ -2200,7 +2199,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -2220,7 +2219,7 @@ impl Arc { /// } /// ``` #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub unsafe fn decrement_strong_count_in(ptr: *const T, alloc: A) { // SAFETY: Upheld by caller. unsafe { drop(Arc::from_raw_in(ptr, alloc)) }; @@ -3142,7 +3141,7 @@ impl Weak { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// /// use std::sync::Weak; /// use std::alloc::System; @@ -3151,7 +3150,7 @@ impl Weak { /// assert!(empty.upgrade().is_none()); /// ``` #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn new_in(alloc: A) -> Weak { Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc } } @@ -3250,7 +3249,7 @@ impl Weak { impl Weak { /// Returns a reference to the underlying allocator. #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn allocator(&self) -> &A { &self.alloc } @@ -3309,7 +3308,7 @@ impl Weak { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::sync::{Arc, Weak}; /// use std::alloc::System; /// @@ -3327,7 +3326,7 @@ impl Weak { /// [`from_raw_in`]: Weak::from_raw_in /// [`as_ptr`]: Weak::as_ptr #[must_use = "losing the pointer will leak memory"] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn into_raw_with_allocator(self) -> (*const T, A) { let this = mem::ManuallyDrop::new(self); let result = this.as_ptr(); @@ -3379,7 +3378,7 @@ impl Weak { /// [`into_raw`]: Weak::into_raw /// [`upgrade`]: Weak::upgrade #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { // See Weak::as_ptr for context on how the input pointer is derived. @@ -4542,7 +4541,7 @@ impl core::error::Error for Arc { #[unstable(feature = "unique_rc_arc", issue = "112566")] pub struct UniqueArc< T: ?Sized, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { ptr: NonNull>, // Define the ownership of `ArcInner` for drop-check @@ -4816,7 +4815,7 @@ impl UniqueArc { /// point to the new [`Arc`]. #[cfg(not(no_global_oom_handling))] #[unstable(feature = "unique_rc_arc", issue = "112566")] - // #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "allocator_api", issue = "163177")] #[must_use] pub fn new_in(data: T, alloc: A) -> Self { let (ptr, alloc) = Box::into_non_null_with_allocator(Box::new_in( @@ -4835,7 +4834,7 @@ impl UniqueArc { /// 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")] + // #[unstable(feature = "allocator_api", issue = "163177")] pub fn try_new_in(data: T, alloc: A) -> Result { let (ptr, alloc) = Box::into_non_null_with_allocator(Box::try_new_in( ArcInner { @@ -4852,7 +4851,7 @@ impl UniqueArc { /// Consumes the `UniqueArc`, returning its wrapped value and allocator. #[unstable(feature = "unique_rc_arc", issue = "112566")] - // #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "allocator_api", issue = "163177")] #[must_use] pub fn unwrap_with_allocator(this: Self) -> (T, A) { let inner_ptr = this.ptr; @@ -5159,7 +5158,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueArc { } } -#[unstable(feature = "allocator_api", issue = "32838")] +#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] unsafe impl Allocator for Arc { #[inline] fn allocate(&self, layout: Layout) -> Result, AllocError> { @@ -5211,5 +5210,5 @@ unsafe impl Allocator for Arc { } } -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl AllocatorClone for Arc {} diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index df3ff0a9b769f..a4059db012c63 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -21,7 +21,7 @@ use crate::alloc::{Allocator, Global}; pub struct Drain< 'a, T: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator + 'a = Global, > { /// Index of tail to preserve pub(super) tail_start: usize, @@ -58,7 +58,7 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { } /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[must_use] #[inline] pub fn allocator(&self) -> &A { diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs index 366ee1c4e0cbf..4396798067942 100644 --- a/library/alloc/src/vec/extract_if.rs +++ b/library/alloc/src/vec/extract_if.rs @@ -22,7 +22,7 @@ pub struct ExtractIf< 'a, T, F, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { vec: &'a mut Vec, /// The index of the item that will be inspected by the next call to `next`. @@ -51,7 +51,7 @@ impl<'a, T, F, A: Allocator> ExtractIf<'a, T, F, A> { } /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn allocator(&self) -> &A { self.vec.allocator() diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index d99d2126810ba..48b1db0d5bf49 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -46,7 +46,7 @@ macro non_null { #[rustc_insignificant_dtor] pub struct IntoIter< T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { pub(super) buf: NonNull, pub(super) phantom: PhantomData, @@ -112,7 +112,7 @@ impl IntoIter { } /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn allocator(&self) -> &A { &self.alloc diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 7a9ac8bae32e2..4537e50e634f2 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -436,7 +436,10 @@ mod sve_retain; #[rustc_insignificant_dtor] #[doc(alias = "list")] #[doc(alias = "vector")] -pub struct Vec { +pub struct Vec< + T, + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] A: Allocator = Global, +> { buf: RawVec, len: usize, } @@ -940,8 +943,6 @@ const impl Vec { /// # Examples /// /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::System; /// /// let mut vec = Vec::with_capacity_in(10, System); @@ -968,7 +969,7 @@ const impl Vec { /// assert_eq!(vec_units.capacity(), usize::MAX); /// ``` #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } } @@ -1055,14 +1056,13 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::System; /// /// let vec: Vec = Vec::new_in(System); /// ``` #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "allocator_ext", issue = "163177")] pub const fn new_in(alloc: A) -> Self { Vec { buf: RawVec::new_in(alloc), len: 0 } } @@ -1079,7 +1079,7 @@ impl Vec { /// Returns an error if the capacity exceeds `isize::MAX` _bytes_, /// or if the allocator reports allocation failure. #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] // #[unstable(feature = "try_with_capacity", issue = "91913")] pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result { Ok(Vec { buf: RawVec::try_with_capacity_in(capacity, alloc)?, len: 0 }) @@ -1133,8 +1133,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::System; /// /// use std::ptr; @@ -1162,8 +1160,6 @@ impl Vec { /// Using memory that was allocated elsewhere: /// /// ```rust - /// #![feature(allocator_api)] - /// /// use std::alloc::{AllocError, Allocator, Global, Layout}; /// /// fn main() { @@ -1185,8 +1181,8 @@ impl Vec { /// } /// ``` #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub const unsafe fn from_raw_parts_in( ptr: *mut T, length: usize, @@ -1251,8 +1247,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::System; /// /// let mut v = Vec::with_capacity_in(3, System); @@ -1278,8 +1272,6 @@ impl Vec { /// Using memory that was allocated elsewhere: /// /// ```rust - /// #![feature(allocator_api)] - /// /// use std::alloc::{AllocError, Allocator, Global, Layout}; /// /// fn main() { @@ -1301,8 +1293,8 @@ impl Vec { /// } /// ``` #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub const unsafe fn from_parts_in( ptr: NonNull, length: usize, @@ -1335,8 +1327,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::System; /// /// let mut v: Vec = Vec::new_in(System); @@ -1356,8 +1346,8 @@ impl Vec { /// assert_eq!(rebuilt, [4294967295, 0, 1]); /// ``` #[must_use = "losing the pointer will leak memory"] - #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[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); let len = me.len(); @@ -1386,8 +1376,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(allocator_api)] - /// /// use std::alloc::System; /// /// let mut v: Vec = Vec::new_in(System); @@ -1407,8 +1395,8 @@ impl Vec { /// assert_eq!(rebuilt, [4294967295, 0, 1]); /// ``` #[must_use = "losing the pointer will leak memory"] - #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[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(); // SAFETY: A `Vec` always has a non-null pointer. @@ -2126,7 +2114,7 @@ impl Vec { } /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] #[inline] pub const fn allocator(&self) -> &A { @@ -3822,7 +3810,7 @@ pub fn from_elem(elem: T, n: usize) -> Vec { #[doc(hidden)] #[cfg(not(no_global_oom_handling))] -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn from_elem_in(elem: T, n: usize, alloc: A) -> Vec { ::from_elem(elem, n, alloc) } diff --git a/library/alloc/src/vec/peek_mut.rs b/library/alloc/src/vec/peek_mut.rs index 979bcaa1111d5..f84262352289a 100644 --- a/library/alloc/src/vec/peek_mut.rs +++ b/library/alloc/src/vec/peek_mut.rs @@ -15,7 +15,7 @@ use crate::fmt; pub struct PeekMut< 'a, T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { vec: &'a mut Vec, } diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs index 534db037c3bdc..103bc5e00e521 100644 --- a/library/alloc/src/vec/splice.rs +++ b/library/alloc/src/vec/splice.rs @@ -20,7 +20,7 @@ use crate::alloc::{Allocator, Global}; pub struct Splice< 'a, I: Iterator + 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator + 'a = Global, > { pub(super) drain: Drain<'a, I::Item, A>, pub(super) replace_with: I, diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 50c58092bd41a..76550081a703c 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -13,7 +13,7 @@ // // Library features: // tidy-alphabetical-start -#![feature(allocator_api)] +#![feature(allocator_ext)] #![feature(array_into_iter_constructors)] #![feature(char_internals)] #![feature(const_alloc_error)] diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index b2a3e8f8f8e2a..9bcb545c8e87d 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -3,7 +3,7 @@ #![deny(implicit_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] #![feature(alloc_io)] -#![feature(allocator_api)] +#![feature(allocator_ext)] #![feature(binary_heap_drain_sorted)] #![feature(binary_heap_into_iter_sorted)] #![feature(binary_heap_pop_if)] diff --git a/library/alloctests/tests/vec_deque_alloc_error.rs b/library/alloctests/tests/vec_deque_alloc_error.rs index 21a9118a05bd6..863af31e1cd1e 100644 --- a/library/alloctests/tests/vec_deque_alloc_error.rs +++ b/library/alloctests/tests/vec_deque_alloc_error.rs @@ -1,4 +1,4 @@ -#![feature(alloc_error_hook, allocator_api)] +#![feature(alloc_error_hook, allocator_ext)] use std::alloc::{AllocError, Allocator, Layout, System, set_alloc_error_hook}; use std::collections::VecDeque; diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 3355880478509..1ca14b1cde064 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -27,19 +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. -#[unstable(feature = "allocator_api", issue = "32838")] +#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct AllocError; -#[unstable( - feature = "allocator_api", - reason = "the precise API and guarantees it provides may be tweaked.", - issue = "32838" -)] +#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] impl Error for AllocError {} // (we need this for downstream impl of trait Error) -#[unstable(feature = "allocator_api", issue = "32838")] +#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] impl fmt::Display for AllocError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("memory allocation failed") @@ -196,7 +192,7 @@ impl fmt::Display for AllocError { // and make sure they cannot be triggered before relaxing this: // https://rust.tf/156490 // https://rust.tf/159982 -#[unstable(feature = "allocator_api", issue = "32838")] +#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub const unsafe trait Allocator { /// Attempts to allocate a block of memory. @@ -231,6 +227,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")] fn allocate(&self, layout: Layout) -> Result, AllocError>; /// Behaves like `allocate`, but also ensures that the returned memory is zero-initialized. @@ -248,6 +245,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")] fn allocate_zeroed(&self, layout: Layout) -> Result, AllocError> { let ptr = self.allocate(layout)?; // SAFETY: `alloc` returns a valid memory block @@ -271,6 +269,7 @@ pub const unsafe trait Allocator { /// /// [*currently allocated*]: #currently-allocated-memory /// [*fit*]: #memory-fitting + #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] unsafe fn deallocate(&self, ptr: NonNull, layout: Layout); /// Attempts to extend the memory block. @@ -312,6 +311,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")] unsafe fn grow( &self, ptr: NonNull, @@ -372,6 +372,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")] unsafe fn grow_zeroed( &self, ptr: NonNull, @@ -438,6 +439,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")] unsafe fn shrink( &self, ptr: NonNull, @@ -521,7 +523,7 @@ pub const unsafe trait Allocator { /// [`std::thread::park`]: ../../std/thread/fn.park.html /// [`std::thread::Thread`]: ../../std/thread/struct.Thread.html /// [`unpark`]: ../../std/thread/struct.Thread.html#method.unpark -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[expect(multiple_supertrait_upcastable)] pub unsafe trait GlobalAllocator: StaticAllocator + Sync + 'static {} @@ -537,7 +539,7 @@ pub unsafe trait GlobalAllocator: StaticAllocator + Sync + 'static {} /// It must also be the case that types which are `AllocatorClone` are either explicitly not /// copyable (such as by containing a `!Copy` field) or that copying them also respects allocator /// equivalence as if it had been a clone. -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub unsafe trait AllocatorClone: Allocator + Clone {} /// Marks that an allocator and its supertypes will never invalidate currently allocated @@ -568,10 +570,10 @@ pub unsafe trait AllocatorClone: Allocator + Clone {} /// /// [`Pin`]: ../../core/pin/struct.Pin.html /// [unsound]: https://github.com/rust-lang/rust/issues/157089 -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub unsafe trait StaticAllocator: Allocator {} -#[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 &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