From 845da883816d60b6a3c8b161ecf5d3c306867afa Mon Sep 17 00:00:00 2001 From: Aatif Syed Date: Fri, 28 Nov 2025 00:52:38 +0000 Subject: [PATCH 01/27] refactor: remove Ord bound from BinaryHeap::new etc --- library/alloc/src/collections/binary_heap/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 63828b482b9a9..a221c66d31d5c 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -466,7 +466,7 @@ impl Clone for BinaryHeap { } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for BinaryHeap { +impl Default for BinaryHeap { /// Creates an empty `BinaryHeap`. #[inline] fn default() -> BinaryHeap { @@ -496,7 +496,7 @@ impl Drop for RebuildOnDrop<'_, T, A> { } } -impl BinaryHeap { +impl BinaryHeap { /// Creates an empty `BinaryHeap` as a max-heap. /// /// # Examples @@ -537,7 +537,7 @@ impl BinaryHeap { } } -impl BinaryHeap { +impl BinaryHeap { /// Creates an empty `BinaryHeap` as a max-heap, using `A` as allocator. /// /// # Examples @@ -615,7 +615,9 @@ impl BinaryHeap { pub fn peek_mut(&mut self) -> Option> { if self.is_empty() { None } else { Some(PeekMut { heap: self, original_len: None }) } } +} +impl BinaryHeap { /// Removes the greatest item from the binary heap and returns it, or `None` if it /// is empty. /// From fcf24266b4feb4f788ad1d51d8f056cce039cf00 Mon Sep 17 00:00:00 2001 From: Aatif Syed Date: Fri, 28 Nov 2025 01:19:07 +0000 Subject: [PATCH 02/27] fix: BinaryHeap::peek_mut --- library/alloc/src/collections/binary_heap/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index a221c66d31d5c..5710b2a3a91d8 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -581,7 +581,9 @@ impl BinaryHeap { pub fn with_capacity_in(capacity: usize, alloc: A) -> BinaryHeap { BinaryHeap { data: Vec::with_capacity_in(capacity, alloc) } } +} +impl BinaryHeap { /// Returns a mutable reference to the greatest item in the binary heap, or /// `None` if it is empty. /// @@ -615,9 +617,7 @@ impl BinaryHeap { pub fn peek_mut(&mut self) -> Option> { if self.is_empty() { None } else { Some(PeekMut { heap: self, original_len: None }) } } -} -impl BinaryHeap { /// Removes the greatest item from the binary heap and returns it, or `None` if it /// is empty. /// From 9156b540aa35820a87c377b780e6058fe5dface9 Mon Sep 17 00:00:00 2001 From: Guilherme Luiz Date: Fri, 9 Jan 2026 19:33:18 -0300 Subject: [PATCH 03/27] =?UTF-8?q?Update=20to=5Fuppercase=20docs=20to=20avo?= =?UTF-8?q?id=20=C3=9F->SS=20example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/core/src/char/methods.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 89cb069723921..c30edeed580a8 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1147,7 +1147,7 @@ impl char { /// As an iterator: /// /// ``` - /// for c in 'ß'.to_uppercase() { + /// for c in 'ffi'.to_uppercase() { /// print!("{c}"); /// } /// println!(); @@ -1156,13 +1156,13 @@ impl char { /// Using `println!` directly: /// /// ``` - /// println!("{}", 'ß'.to_uppercase()); + /// println!("{}", 'ffi'.to_uppercase()); /// ``` /// /// Both are equivalent to: /// /// ``` - /// println!("SS"); + /// println!("FFI"); /// ``` /// /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string): @@ -1171,7 +1171,7 @@ impl char { /// assert_eq!('c'.to_uppercase().to_string(), "C"); /// /// // Sometimes the result is more than one character: - /// assert_eq!('ß'.to_uppercase().to_string(), "SS"); + /// assert_eq!('ffi'.to_uppercase().to_string(), "FFI"); /// /// // Characters that do not have both uppercase and lowercase /// // convert into themselves. From c10f0dd1947645259a7e1e9f436956aea73d1cdf Mon Sep 17 00:00:00 2001 From: Guilherme Luiz Date: Sat, 10 Jan 2026 14:09:21 -0300 Subject: [PATCH 04/27] =?UTF-8?q?Add=20comment=20to=20clarify=20that=20'?= =?UTF-8?q?=EF=AC=83'=20is=20a=20single=20Unicode=20code=20point=20mapping?= =?UTF-8?q?=20to=20FFI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/core/src/char/methods.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index c30edeed580a8..0acb3e964f54c 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1143,6 +1143,7 @@ impl char { /// [Unicode Standard]: https://www.unicode.org/versions/latest/ /// /// # Examples + /// `'ffi'` (U+FB03) is a single Unicode code point (a ligature) that maps to "FFI" in uppercase. /// /// As an iterator: /// From 6b5a1a51e5f3f1cf1bffb072c4d6ebaa04400744 Mon Sep 17 00:00:00 2001 From: Guilherme Luiz Date: Mon, 12 Jan 2026 16:39:54 -0300 Subject: [PATCH 05/27] =?UTF-8?q?Switch=20from=20=EF=AC=83=20to=20?= =?UTF-8?q?=EF=AC=85=20ligature=20for=20better=20visual=20clarity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/core/src/char/methods.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 0acb3e964f54c..87b328c912878 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1143,12 +1143,12 @@ impl char { /// [Unicode Standard]: https://www.unicode.org/versions/latest/ /// /// # Examples - /// `'ffi'` (U+FB03) is a single Unicode code point (a ligature) that maps to "FFI" in uppercase. + /// `'ſt'` (U+FB05) is a single Unicode code point (a ligature) that maps to "ST" in uppercase. /// /// As an iterator: /// /// ``` - /// for c in 'ffi'.to_uppercase() { + /// for c in 'ſt'.to_uppercase() { /// print!("{c}"); /// } /// println!(); @@ -1157,13 +1157,13 @@ impl char { /// Using `println!` directly: /// /// ``` - /// println!("{}", 'ffi'.to_uppercase()); + /// println!("{}", 'ſt'.to_uppercase()); /// ``` /// /// Both are equivalent to: /// /// ``` - /// println!("FFI"); + /// println!("ST"); /// ``` /// /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string): @@ -1172,7 +1172,7 @@ impl char { /// assert_eq!('c'.to_uppercase().to_string(), "C"); /// /// // Sometimes the result is more than one character: - /// assert_eq!('ffi'.to_uppercase().to_string(), "FFI"); + /// assert_eq!('ſt'.to_uppercase().to_string(), "ST"); /// /// // Characters that do not have both uppercase and lowercase /// // convert into themselves. From c98b90eaadc1a4ba4fca60572f3ce75f6f44b216 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 12 Jan 2026 17:26:23 -0500 Subject: [PATCH 06/27] std: Change UEFI env vars to volatile storage The UEFI variables set by the env vars should be volatile, otherwise they will persist after reboot and use up scarce non-volatile storage. --- library/std/src/sys/env/uefi.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/env/uefi.rs b/library/std/src/sys/env/uefi.rs index 5fe29a47a2ea1..af16a02642a4c 100644 --- a/library/std/src/sys/env/uefi.rs +++ b/library/std/src/sys/env/uefi.rs @@ -95,8 +95,8 @@ mod uefi_env { val_ptr: *mut r_efi::efi::Char16, ) -> io::Result<()> { let shell = helpers::open_shell().ok_or(unsupported_err())?; - let r = - unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, r_efi::efi::Boolean::FALSE) }; + let volatile = r_efi::efi::Boolean::TRUE; + let r = unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, volatile) }; if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } } } From cafe91749f491d8d4c10893f1dfa6298951dc9e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 12 Jan 2026 22:38:32 +0000 Subject: [PATCH 07/27] On unmet trait bound, mention if trait is unstable --- .../error_reporting/traits/fulfillment_errors.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 9 ++++++++- tests/ui/abi/issues/issue-22565-rust-call.stderr | 4 ++-- tests/ui/async-await/coroutine-not-future.stderr | 6 +++--- tests/ui/async-await/issue-61076.rs | 4 ++-- tests/ui/async-await/issue-61076.stderr | 4 ++-- tests/ui/async-await/issue-84841.stderr | 2 +- tests/ui/async-await/try-in-sync.stderr | 2 +- .../adt_const_params/const_param_ty_bad.stderr | 12 ++++++------ .../const_param_ty_bad_empty_array.stderr | 2 +- ...st_param_ty_generic_bounds_do_not_hold.stderr | 6 +++--- .../const_param_ty_impl_no_structural_eq.stderr | 4 ++-- tests/ui/coroutine/gen_block_is_coro.stderr | 6 +++--- tests/ui/error-codes/E0059.stderr | 4 ++-- tests/ui/extern/extern-types-unsized.stderr | 4 ++-- tests/ui/extern/unsized-extern-derefmove.stderr | 6 +++--- .../feature-gate-sized-hierarchy.stderr | 2 +- .../rust-call-abi-not-a-tuple-ice-81974.stderr | 16 ++++++++-------- .../ui/mir/validate/validate-unsize-cast.stderr | 2 +- .../overloaded/overloaded-calls-nontuple.stderr | 12 ++++++------ .../deref-patterns/recursion-limit.stderr | 2 +- .../deref-patterns/unsatisfied-bounds.stderr | 2 +- tests/ui/proc-macro/quote/not-quotable.stderr | 2 +- tests/ui/range/range-1.stderr | 2 +- .../disallowed-positions.e2021.stderr | 6 +++--- .../disallowed-positions.e2024.stderr | 6 +++--- tests/ui/sized-hierarchy/default-bound.stderr | 2 +- tests/ui/sized-hierarchy/impls.stderr | 10 +++++----- .../sized-hierarchy/pretty-print-opaque.stderr | 6 +++--- tests/ui/specialization/issue-44861.stderr | 2 +- tests/ui/suggestions/fn-trait-notation.stderr | 4 ++-- tests/ui/suggestions/issue-72766.stderr | 2 +- tests/ui/suggestions/issue-97704.stderr | 2 +- .../unstable-trait-suggestion.stderr | 4 ++-- tests/ui/traits/issue-71036.rs | 2 +- tests/ui/traits/issue-71036.stderr | 2 +- .../ui/traits/next-solver/coroutine.fail.stderr | 2 +- .../higher-ranked-upcasting-ub.next.stderr | 2 +- .../unsize-goal-escaping-bounds.current.stderr | 2 +- tests/ui/transmutability/assoc-bound.stderr | 2 +- .../dont-assume-err-is-yes-issue-126377.stderr | 2 +- .../transmutability/references/unsafecell.stderr | 8 ++++---- .../try-block-bad-type-heterogeneous.stderr | 4 ++-- tests/ui/try-block/try-block-bad-type.stderr | 4 ++-- tests/ui/try-block/try-block-in-while.stderr | 2 +- tests/ui/try-trait/try-operator-on-main.stderr | 6 +++--- tests/ui/tuple/builtin-fail.stderr | 8 ++++---- tests/ui/type/pattern_types/nested.stderr | 14 +++++++------- tests/ui/typeck/issue-57404.stderr | 2 +- .../non-tupled-arg-mismatch.stderr | 2 +- 50 files changed, 116 insertions(+), 109 deletions(-) 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 8762607edf5dc..00d06779e652e 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 @@ -681,7 +681,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Ambiguous predicates should never error | ty::PredicateKind::Ambiguous // We never return Err when proving UnstableFeature goal. - | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature{ .. }) + | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature { .. }) | ty::PredicateKind::NormalizesTo { .. } | ty::PredicateKind::AliasRelate { .. } | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType { .. }) => { 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 511e9e85b5f60..c9e07175773b8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -5515,7 +5515,14 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>( }; if let ty::PredicatePolarity::Positive = trait_predicate.polarity() { format!( - "{pre_message}the trait `{}` is not implemented for{desc} `{}`", + "{pre_message}the {}trait `{}` is not implemented for{desc} `{}`", + if tcx.lookup_stability(trait_predicate.def_id()).map(|s| s.level.is_stable()) + == Some(false) + { + "nightly-only, unstable " + } else { + "" + }, trait_predicate.print_modifiers_and_trait_path(), tcx.short_string(trait_predicate.self_ty().skip_binder(), long_ty_path), ) diff --git a/tests/ui/abi/issues/issue-22565-rust-call.stderr b/tests/ui/abi/issues/issue-22565-rust-call.stderr index 3e296bdaea41d..90fa210fa2faf 100644 --- a/tests/ui/abi/issues/issue-22565-rust-call.stderr +++ b/tests/ui/abi/issues/issue-22565-rust-call.stderr @@ -2,7 +2,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup --> $DIR/issue-22565-rust-call.rs:3:1 | LL | extern "rust-call" fn b(_i: i32) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `i32` error: functions with the "rust-call" ABI must take a single non-self tuple argument --> $DIR/issue-22565-rust-call.rs:17:5 @@ -32,7 +32,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup --> $DIR/issue-22565-rust-call.rs:27:7 | LL | b(10); - | ^^ the trait `std::marker::Tuple` is not implemented for `i32` + | ^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `i32` error: functions with the "rust-call" ABI must take a single non-self tuple argument --> $DIR/issue-22565-rust-call.rs:29:5 diff --git a/tests/ui/async-await/coroutine-not-future.stderr b/tests/ui/async-await/coroutine-not-future.stderr index b0f371f6706d1..b55faf39ce69a 100644 --- a/tests/ui/async-await/coroutine-not-future.stderr +++ b/tests/ui/async-await/coroutine-not-future.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `impl Future: Coroutine<_>` is not sa --> $DIR/coroutine-not-future.rs:36:21 | LL | takes_coroutine(async_fn()); - | --------------- ^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future` + | --------------- ^^^^^^^^^^ the nightly-only, unstable trait `Coroutine<_>` is not implemented for `impl Future` | | | required by a bound introduced by this call | @@ -16,7 +16,7 @@ error[E0277]: the trait bound `impl Future: Coroutine<_>` is not sa --> $DIR/coroutine-not-future.rs:38:21 | LL | takes_coroutine(returns_async_block()); - | --------------- ^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future` + | --------------- ^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Coroutine<_>` is not implemented for `impl Future` | | | required by a bound introduced by this call | @@ -30,7 +30,7 @@ error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:40:21: --> $DIR/coroutine-not-future.rs:40:21 | LL | takes_coroutine(async {}); - | --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:40:21: 40:26}` + | --------------- ^^^^^^^^ the nightly-only, unstable trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:40:21: 40:26}` | | | required by a bound introduced by this call | diff --git a/tests/ui/async-await/issue-61076.rs b/tests/ui/async-await/issue-61076.rs index 0a679a95970ac..6fe7846ea8d92 100644 --- a/tests/ui/async-await/issue-61076.rs +++ b/tests/ui/async-await/issue-61076.rs @@ -4,7 +4,7 @@ use core::future::Future; use core::pin::Pin; use core::task::{Context, Poll}; -struct T; //~ HELP the trait `Try` is not implemented for `T` +struct T; //~ HELP the nightly-only, unstable trait `Try` is not implemented for `T` struct Tuple(i32); @@ -41,7 +41,7 @@ async fn foo() -> Result<(), ()> { async fn bar() -> Result<(), ()> { foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Try` //~^ NOTE the `?` operator cannot be applied to type `impl Future>` - //~| HELP the trait `Try` is not implemented for `impl Future>` + //~| HELP the nightly-only, unstable trait `Try` is not implemented for `impl Future>` //~| HELP consider `await`ing on the `Future` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` diff --git a/tests/ui/async-await/issue-61076.stderr b/tests/ui/async-await/issue-61076.stderr index 7d46abe4a66b3..dd49d00246cdf 100644 --- a/tests/ui/async-await/issue-61076.stderr +++ b/tests/ui/async-await/issue-61076.stderr @@ -4,7 +4,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | foo()?; | ^^^^^^ the `?` operator cannot be applied to type `impl Future>` | - = help: the trait `Try` is not implemented for `impl Future>` + = help: the nightly-only, unstable trait `Try` is not implemented for `impl Future>` help: consider `await`ing on the `Future` | LL | foo().await?; @@ -16,7 +16,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | t?; | ^^ the `?` operator cannot be applied to type `T` | -help: the trait `Try` is not implemented for `T` +help: the nightly-only, unstable trait `Try` is not implemented for `T` --> $DIR/issue-61076.rs:7:1 | LL | struct T; diff --git a/tests/ui/async-await/issue-84841.stderr b/tests/ui/async-await/issue-84841.stderr index 0d008477310a7..6c714ce7828ce 100644 --- a/tests/ui/async-await/issue-84841.stderr +++ b/tests/ui/async-await/issue-84841.stderr @@ -4,7 +4,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | test()?; | ^^^^^^^ the `?` operator cannot be applied to type `impl Future` | - = help: the trait `Try` is not implemented for `impl Future` + = help: the nightly-only, unstable trait `Try` is not implemented for `impl Future` error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/issue-84841.rs:9:11 diff --git a/tests/ui/async-await/try-in-sync.stderr b/tests/ui/async-await/try-in-sync.stderr index bc7a6bd015129..0957339a4dc58 100644 --- a/tests/ui/async-await/try-in-sync.stderr +++ b/tests/ui/async-await/try-in-sync.stderr @@ -4,7 +4,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | foo()?; | ^^^^^^ the `?` operator cannot be applied to type `impl Future>` | - = help: the trait `Try` is not implemented for `impl Future>` + = help: the nightly-only, unstable trait `Try` is not implemented for `impl Future>` note: this implements `Future` and its output type supports `?`, but the future cannot be awaited in a synchronous function --> $DIR/try-in-sync.rs:6:10 | diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr index 5109dccd96a1d..be63c9e5c046b 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr @@ -2,7 +2,7 @@ error[E0277]: `fn() {main}` can't be used as a const parameter type --> $DIR/const_param_ty_bad.rs:7:11 | LL | check(main); - | ----- ^^^^ the trait `ConstParamTy_` is not implemented for fn item `fn() {main}` + | ----- ^^^^ the nightly-only, unstable trait `ConstParamTy_` is not implemented for fn item `fn() {main}` | | | required by a bound introduced by this call | @@ -24,7 +24,7 @@ LL | check(|| {}); | | | required by a bound introduced by this call | - = help: the trait `ConstParamTy_` is not implemented for closure `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}` + = help: the nightly-only, unstable trait `ConstParamTy_` is not implemented for closure `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}` note: required by a bound in `check` --> $DIR/const_param_ty_bad.rs:4:18 | @@ -40,7 +40,7 @@ error[E0277]: `fn()` can't be used as a const parameter type --> $DIR/const_param_ty_bad.rs:9:11 | LL | check(main as fn()); - | ----- ^^^^^^^^^^^^ the trait `ConstParamTy_` is not implemented for `fn()` + | ----- ^^^^^^^^^^^^ the nightly-only, unstable trait `ConstParamTy_` is not implemented for `fn()` | | | required by a bound introduced by this call | @@ -58,7 +58,7 @@ error[E0277]: `&mut ()` can't be used as a const parameter type --> $DIR/const_param_ty_bad.rs:10:11 | LL | check(&mut ()); - | ----- ^^^^^^^ the trait `ConstParamTy_` is not implemented for `&mut ()` + | ----- ^^^^^^^ the nightly-only, unstable trait `ConstParamTy_` is not implemented for `&mut ()` | | | required by a bound introduced by this call | @@ -78,7 +78,7 @@ error[E0277]: `*mut ()` can't be used as a const parameter type --> $DIR/const_param_ty_bad.rs:11:11 | LL | check(&mut () as *mut ()); - | ----- ^^^^^^^^^^^^^^^^^^ the trait `ConstParamTy_` is not implemented for `*mut ()` + | ----- ^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `ConstParamTy_` is not implemented for `*mut ()` | | | required by a bound introduced by this call | @@ -98,7 +98,7 @@ error[E0277]: `*const ()` can't be used as a const parameter type --> $DIR/const_param_ty_bad.rs:12:11 | LL | check(&() as *const ()); - | ----- ^^^^^^^^^^^^^^^^ the trait `ConstParamTy_` is not implemented for `*const ()` + | ----- ^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `ConstParamTy_` is not implemented for `*const ()` | | | required by a bound introduced by this call | diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr index 373ac9435daf1..460b7420e8c04 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr @@ -4,7 +4,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type LL | check::<[NotParam; 0]>(); | ^^^^^^^^^^^^^ unsatisfied trait bound | -help: the trait `ConstParamTy_` is not implemented for `NotParam` +help: the nightly-only, unstable trait `ConstParamTy_` is not implemented for `NotParam` --> $DIR/const_param_ty_bad_empty_array.rs:5:1 | LL | struct NotParam; diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr index ca2aa3adcb7a6..fd1162fe08e30 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr @@ -4,7 +4,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type LL | check::<&NotParam>(); | ^^^^^^^^^ unsatisfied trait bound | -help: the trait `ConstParamTy_` is not implemented for `NotParam` +help: the nightly-only, unstable trait `ConstParamTy_` is not implemented for `NotParam` --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:5:1 | LL | struct NotParam; @@ -22,7 +22,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type LL | check::<[NotParam]>(); | ^^^^^^^^^^ unsatisfied trait bound | -help: the trait `ConstParamTy_` is not implemented for `NotParam` +help: the nightly-only, unstable trait `ConstParamTy_` is not implemented for `NotParam` --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:5:1 | LL | struct NotParam; @@ -40,7 +40,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type LL | check::<[NotParam; 17]>(); | ^^^^^^^^^^^^^^ unsatisfied trait bound | -help: the trait `ConstParamTy_` is not implemented for `NotParam` +help: the nightly-only, unstable trait `ConstParamTy_` is not implemented for `NotParam` --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:5:1 | LL | struct NotParam; diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr index c6b791ed9674a..ca2a693d48ceb 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr @@ -18,7 +18,7 @@ error[E0277]: the type `CantParam` does not `#[derive(PartialEq)]` LL | impl std::marker::ConstParamTy_ for CantParam {} | ^^^^^^^^^ unsatisfied trait bound | -help: the trait `StructuralPartialEq` is not implemented for `CantParam` +help: the nightly-only, unstable trait `StructuralPartialEq` is not implemented for `CantParam` --> $DIR/const_param_ty_impl_no_structural_eq.rs:8:1 | LL | struct CantParam(ImplementsConstParamTy); @@ -46,7 +46,7 @@ error[E0277]: the type `CantParamDerive` does not `#[derive(PartialEq)]` LL | #[derive(std::marker::ConstParamTy)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound | -help: the trait `StructuralPartialEq` is not implemented for `CantParamDerive` +help: the nightly-only, unstable trait `StructuralPartialEq` is not implemented for `CantParamDerive` --> $DIR/const_param_ty_impl_no_structural_eq.rs:17:1 | LL | struct CantParamDerive(ImplementsConstParamTy); diff --git a/tests/ui/coroutine/gen_block_is_coro.stderr b/tests/ui/coroutine/gen_block_is_coro.stderr index 444f0eca1d54c..fac09f6000597 100644 --- a/tests/ui/coroutine/gen_block_is_coro.stderr +++ b/tests/ui/coroutine/gen_block_is_coro.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:8:5: 8:8}: C --> $DIR/gen_block_is_coro.rs:7:13 | LL | fn foo() -> impl Coroutine { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:8:5: 8:8}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:8:5: 8:8}` LL | gen { yield 42 } | ---------------- return type was inferred to be `{gen block@$DIR/gen_block_is_coro.rs:8:5: 8:8}` here @@ -10,7 +10,7 @@ error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:12:5: 12:8}: --> $DIR/gen_block_is_coro.rs:11:13 | LL | fn bar() -> impl Coroutine { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:12:5: 12:8}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:12:5: 12:8}` LL | gen { yield 42 } | ---------------- return type was inferred to be `{gen block@$DIR/gen_block_is_coro.rs:12:5: 12:8}` here @@ -18,7 +18,7 @@ error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:16:5: 16:8}: --> $DIR/gen_block_is_coro.rs:15:13 | LL | fn baz() -> impl Coroutine { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:16:5: 16:8}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:16:5: 16:8}` LL | gen { yield 42 } | ---------------- return type was inferred to be `{gen block@$DIR/gen_block_is_coro.rs:16:5: 16:8}` here diff --git a/tests/ui/error-codes/E0059.stderr b/tests/ui/error-codes/E0059.stderr index 698ee0a2a9029..43191db8be109 100644 --- a/tests/ui/error-codes/E0059.stderr +++ b/tests/ui/error-codes/E0059.stderr @@ -2,7 +2,7 @@ error[E0059]: type parameter to bare `Fn` trait must be a tuple --> $DIR/E0059.rs:3:11 | LL | fn foo>(f: F) -> F::Output { f(3) } - | ^^^^^^^ the trait `std::marker::Tuple` is not implemented for `i32` + | ^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `i32` | note: required by a bound in `Fn` --> $SRC_DIR/core/src/ops/function.rs:LL:COL @@ -11,7 +11,7 @@ error[E0277]: `i32` is not a tuple --> $DIR/E0059.rs:3:41 | LL | fn foo>(f: F) -> F::Output { f(3) } - | ^^^^ the trait `std::marker::Tuple` is not implemented for `i32` + | ^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `i32` error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit --> $DIR/E0059.rs:3:41 diff --git a/tests/ui/extern/extern-types-unsized.stderr b/tests/ui/extern/extern-types-unsized.stderr index 43dd9800d6d30..9953e5686632a 100644 --- a/tests/ui/extern/extern-types-unsized.stderr +++ b/tests/ui/extern/extern-types-unsized.stderr @@ -65,7 +65,7 @@ error[E0277]: the size for values of type `A` cannot be known LL | assert_sized::>(); | ^^^^^^ doesn't have a known size | - = help: the trait `MetaSized` is not implemented for `A` + = help: the nightly-only, unstable trait `MetaSized` is not implemented for `A` note: required by a bound in `Bar` --> $DIR/extern-types-unsized.rs:14:12 | @@ -100,7 +100,7 @@ error[E0277]: the size for values of type `A` cannot be known LL | assert_sized::>>(); | ^^^^^^^^^^^ doesn't have a known size | - = help: the trait `MetaSized` is not implemented for `A` + = help: the nightly-only, unstable trait `MetaSized` is not implemented for `A` note: required by a bound in `Bar` --> $DIR/extern-types-unsized.rs:14:12 | diff --git a/tests/ui/extern/unsized-extern-derefmove.stderr b/tests/ui/extern/unsized-extern-derefmove.stderr index a9efc2e66e3b0..7eb9c6800dc6c 100644 --- a/tests/ui/extern/unsized-extern-derefmove.stderr +++ b/tests/ui/extern/unsized-extern-derefmove.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `Device` cannot be known LL | unsafe fn make_device() -> Box { | ^^^^^^^^^^^ doesn't have a known size | - = help: the trait `MetaSized` is not implemented for `Device` + = help: the nightly-only, unstable trait `MetaSized` is not implemented for `Device` note: required by a bound in `Box` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL @@ -32,7 +32,7 @@ error[E0277]: the size for values of type `Device` cannot be known LL | Box::from_raw(0 as *mut _) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a known size | - = help: the trait `MetaSized` is not implemented for `Device` + = help: the nightly-only, unstable trait `MetaSized` is not implemented for `Device` note: required by a bound in `Box` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL @@ -55,7 +55,7 @@ error[E0277]: the size for values of type `Device` cannot be known LL | let d: Device = unsafe { *make_device() }; | ^^^^^^^^^^^^^ doesn't have a known size | - = help: the trait `MetaSized` is not implemented for `Device` + = help: the nightly-only, unstable trait `MetaSized` is not implemented for `Device` note: required by a bound in `Box` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr b/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr index 6a35fcfb0e8e5..8e97c73c7d21c 100644 --- a/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr +++ b/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr @@ -17,7 +17,7 @@ error[E0277]: the size for values of type `main::Foo` cannot be known LL | needs_metasized::(); | ^^^ doesn't have a known size | - = help: the trait `MetaSized` is not implemented for `main::Foo` + = help: the nightly-only, unstable trait `MetaSized` is not implemented for `main::Foo` note: required by a bound in `needs_metasized` --> $DIR/feature-gate-sized-hierarchy.rs:7:23 | diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr index e7cb82687fa7d..6d7f46fae8050 100644 --- a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr +++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr @@ -2,7 +2,7 @@ error[E0059]: type parameter to bare `FnOnce` trait must be a tuple --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:31:5 | LL | extern "rust-call" fn call_once(mut self, a: A) -> Self::Output { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `A` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `A` | note: required by a bound in `FnOnce` --> $SRC_DIR/core/src/ops/function.rs:LL:COL @@ -15,7 +15,7 @@ error[E0059]: type parameter to bare `FnOnce` trait must be a tuple --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:24:12 | LL | impl FnOnce for CachedFun - | ^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `A` + | ^^^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `A` | note: required by a bound in `FnOnce` --> $SRC_DIR/core/src/ops/function.rs:LL:COL @@ -28,7 +28,7 @@ error[E0059]: type parameter to bare `FnOnce` trait must be a tuple --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:45:5 | LL | extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `A` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `A` | note: required by a bound in `FnOnce` --> $SRC_DIR/core/src/ops/function.rs:LL:COL @@ -41,7 +41,7 @@ error[E0059]: type parameter to bare `FnMut` trait must be a tuple --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:39:12 | LL | impl FnMut for CachedFun - | ^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `A` + | ^^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `A` | note: required by a bound in `FnMut` --> $SRC_DIR/core/src/ops/function.rs:LL:COL @@ -54,7 +54,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:31:5 | LL | extern "rust-call" fn call_once(mut self, a: A) -> Self::Output { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `A` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `A` | help: consider further restricting type parameter `A` with unstable trait `Tuple` | @@ -65,7 +65,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:45:5 | LL | extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `A` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `A` | help: consider further restricting type parameter `A` with unstable trait `Tuple` | @@ -76,7 +76,7 @@ error[E0277]: `A` is not a tuple --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:34:19 | LL | self.call_mut(a) - | -------- ^ the trait `std::marker::Tuple` is not implemented for `A` + | -------- ^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `A` | | | required by a bound introduced by this call | @@ -91,7 +91,7 @@ error[E0277]: `i32` is not a tuple --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:59:26 | LL | cachedcoso.call_once(1); - | --------- ^ the trait `std::marker::Tuple` is not implemented for `i32` + | --------- ^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `i32` | | | required by a bound introduced by this call | diff --git a/tests/ui/mir/validate/validate-unsize-cast.stderr b/tests/ui/mir/validate/validate-unsize-cast.stderr index 8449c6a24bd31..66dd5716826f3 100644 --- a/tests/ui/mir/validate/validate-unsize-cast.stderr +++ b/tests/ui/mir/validate/validate-unsize-cast.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Unsize` is not satisfied --> $DIR/validate-unsize-cast.rs:10:42 | LL | impl CastTo for T {} - | ^ the trait `Unsize` is not implemented for `T` + | ^ the nightly-only, unstable trait `Unsize` is not implemented for `T` | = note: all implementations of `Unsize` are provided automatically by the compiler, see for more information note: required by a bound in `CastTo` diff --git a/tests/ui/overloaded/overloaded-calls-nontuple.stderr b/tests/ui/overloaded/overloaded-calls-nontuple.stderr index 54a9d1f09b52a..b898288c3e4b1 100644 --- a/tests/ui/overloaded/overloaded-calls-nontuple.stderr +++ b/tests/ui/overloaded/overloaded-calls-nontuple.stderr @@ -2,7 +2,7 @@ error[E0059]: type parameter to bare `FnMut` trait must be a tuple --> $DIR/overloaded-calls-nontuple.rs:10:6 | LL | impl FnMut for S { - | ^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `isize` + | ^^^^^^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `isize` | note: required by a bound in `FnMut` --> $SRC_DIR/core/src/ops/function.rs:LL:COL @@ -11,7 +11,7 @@ error[E0059]: type parameter to bare `FnOnce` trait must be a tuple --> $DIR/overloaded-calls-nontuple.rs:18:6 | LL | impl FnOnce for S { - | ^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `isize` + | ^^^^^^^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `isize` | note: required by a bound in `FnOnce` --> $SRC_DIR/core/src/ops/function.rs:LL:COL @@ -20,19 +20,19 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup --> $DIR/overloaded-calls-nontuple.rs:12:5 | LL | extern "rust-call" fn call_mut(&mut self, z: isize) -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `isize` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `isize` error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument --> $DIR/overloaded-calls-nontuple.rs:21:5 | LL | extern "rust-call" fn call_once(mut self, z: isize) -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `isize` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `isize` error[E0277]: `isize` is not a tuple --> $DIR/overloaded-calls-nontuple.rs:23:23 | LL | self.call_mut(z) - | -------- ^ the trait `std::marker::Tuple` is not implemented for `isize` + | -------- ^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `isize` | | | required by a bound introduced by this call | @@ -53,7 +53,7 @@ error[E0277]: `isize` is not a tuple --> $DIR/overloaded-calls-nontuple.rs:29:10 | LL | drop(s(3)) - | ^^^^ the trait `std::marker::Tuple` is not implemented for `isize` + | ^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `isize` error: aborting due to 7 previous errors diff --git a/tests/ui/pattern/deref-patterns/recursion-limit.stderr b/tests/ui/pattern/deref-patterns/recursion-limit.stderr index f6aa92b23adb4..7c140e4493e7b 100644 --- a/tests/ui/pattern/deref-patterns/recursion-limit.stderr +++ b/tests/ui/pattern/deref-patterns/recursion-limit.stderr @@ -12,7 +12,7 @@ error[E0277]: the trait bound `Cyclic: DerefPure` is not satisfied LL | () => {} | ^^ unsatisfied trait bound | -help: the trait `DerefPure` is not implemented for `Cyclic` +help: the nightly-only, unstable trait `DerefPure` is not implemented for `Cyclic` --> $DIR/recursion-limit.rs:8:1 | LL | struct Cyclic; diff --git a/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr index 0b1e8ef497809..3ee6efefe6973 100644 --- a/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr +++ b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `MyPointer: DerefPure` is not satisfied LL | () => {} | ^^ unsatisfied trait bound | -help: the trait `DerefPure` is not implemented for `MyPointer` +help: the nightly-only, unstable trait `DerefPure` is not implemented for `MyPointer` --> $DIR/unsatisfied-bounds.rs:4:1 | LL | struct MyPointer; diff --git a/tests/ui/proc-macro/quote/not-quotable.stderr b/tests/ui/proc-macro/quote/not-quotable.stderr index 62a02638e548b..b00d029946d6a 100644 --- a/tests/ui/proc-macro/quote/not-quotable.stderr +++ b/tests/ui/proc-macro/quote/not-quotable.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `Ipv4Addr: ToTokens` is not satisfied LL | let _ = quote! { $ip }; | ^^^^^^^^^^^^^^ | | - | the trait `ToTokens` is not implemented for `Ipv4Addr` + | the nightly-only, unstable trait `ToTokens` is not implemented for `Ipv4Addr` | required by a bound introduced by this call | = help: the following other types implement trait `ToTokens`: diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr index 8878ba1430974..f2d603b32af0a 100644 --- a/tests/ui/range/range-1.stderr +++ b/tests/ui/range/range-1.stderr @@ -8,7 +8,7 @@ error[E0277]: the trait bound `bool: Step` is not satisfied --> $DIR/range-1.rs:9:14 | LL | for i in false..true {} - | ^^^^^^^^^^^ the trait `Step` is not implemented for `bool` + | ^^^^^^^^^^^ the nightly-only, unstable trait `Step` is not implemented for `bool` | = note: required for `std::ops::Range` to implement `Iterator` = note: required for `std::ops::Range` to implement `IntoIterator` diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.e2021.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.e2021.stderr index 15e7be8c65f2b..40a32880f4071 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.e2021.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.e2021.stderr @@ -1137,7 +1137,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `Try` is not implemented for `{integer}` + = help: the nightly-only, unstable trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:224:11 @@ -1198,7 +1198,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `Try` is not implemented for `{integer}` + = help: the nightly-only, unstable trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:333:10 @@ -1217,7 +1217,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `Try` is not implemented for `{integer}` + = help: the nightly-only, unstable trait `Try` is not implemented for `{integer}` error: aborting due to 134 previous errors diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.e2024.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.e2024.stderr index 20af65cf89a2a..21167cf63d176 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.e2024.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.e2024.stderr @@ -1083,7 +1083,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `Try` is not implemented for `{integer}` + = help: the nightly-only, unstable trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:224:11 @@ -1144,7 +1144,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `Try` is not implemented for `{integer}` + = help: the nightly-only, unstable trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:333:10 @@ -1163,7 +1163,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `Try` is not implemented for `{integer}` + = help: the nightly-only, unstable trait `Try` is not implemented for `{integer}` error: aborting due to 125 previous errors diff --git a/tests/ui/sized-hierarchy/default-bound.stderr b/tests/ui/sized-hierarchy/default-bound.stderr index 0a4ea6f44d8ed..9929e2dba524a 100644 --- a/tests/ui/sized-hierarchy/default-bound.stderr +++ b/tests/ui/sized-hierarchy/default-bound.stderr @@ -76,7 +76,7 @@ error[E0277]: the size for values of type `main::Foo` cannot be known LL | metasized::(); | ^^^ doesn't have a known size | - = help: the trait `MetaSized` is not implemented for `main::Foo` + = help: the nightly-only, unstable trait `MetaSized` is not implemented for `main::Foo` note: required by a bound in `metasized` --> $DIR/default-bound.rs:14:17 | diff --git a/tests/ui/sized-hierarchy/impls.stderr b/tests/ui/sized-hierarchy/impls.stderr index ca70822aad287..25c6c933149fd 100644 --- a/tests/ui/sized-hierarchy/impls.stderr +++ b/tests/ui/sized-hierarchy/impls.stderr @@ -164,7 +164,7 @@ error[E0277]: the size for values of type `main::Foo` cannot be known LL | needs_metasized::(); | ^^^ doesn't have a known size | - = help: the trait `MetaSized` is not implemented for `main::Foo` + = help: the nightly-only, unstable trait `MetaSized` is not implemented for `main::Foo` note: required by a bound in `needs_metasized` --> $DIR/impls.rs:16:23 | @@ -222,7 +222,7 @@ error[E0277]: the size for values of type `main::Foo` cannot be known LL | needs_metasized::<(Foo, Foo)>(); | ^^^^^^^^^^ doesn't have a known size | - = help: within `(main::Foo, main::Foo)`, the trait `MetaSized` is not implemented for `main::Foo` + = help: within `(main::Foo, main::Foo)`, the nightly-only, unstable trait `MetaSized` is not implemented for `main::Foo` = note: required because it appears within the type `(main::Foo, main::Foo)` note: required by a bound in `needs_metasized` --> $DIR/impls.rs:16:23 @@ -273,7 +273,7 @@ error[E0277]: the size for values of type `main::Foo` cannot be known LL | needs_metasized::<(u32, Foo)>(); | ^^^^^^^^^^ doesn't have a known size | - = help: within `(u32, main::Foo)`, the trait `MetaSized` is not implemented for `main::Foo` + = help: within `(u32, main::Foo)`, the nightly-only, unstable trait `MetaSized` is not implemented for `main::Foo` = note: required because it appears within the type `(u32, main::Foo)` note: required by a bound in `needs_metasized` --> $DIR/impls.rs:16:23 @@ -323,7 +323,7 @@ error[E0277]: the size for values of type `main::Foo` cannot be known LL | needs_metasized::(); | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a known size | - = help: within `StructAllFieldsUnsized`, the trait `MetaSized` is not implemented for `main::Foo` + = 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 | @@ -377,7 +377,7 @@ error[E0277]: the size for values of type `main::Foo` cannot be known LL | needs_metasized::(); | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a known size | - = help: within `StructLastFieldUnsized`, the trait `MetaSized` is not implemented for `main::Foo` + = 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 | diff --git a/tests/ui/sized-hierarchy/pretty-print-opaque.stderr b/tests/ui/sized-hierarchy/pretty-print-opaque.stderr index ecf4d912be8fb..9f9289d0f3918 100644 --- a/tests/ui/sized-hierarchy/pretty-print-opaque.stderr +++ b/tests/ui/sized-hierarchy/pretty-print-opaque.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `impl Tr + PointeeSized` cannot be kno LL | pub fn pointeesized() -> Box { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a known size | - = help: the trait `MetaSized` is not implemented for `impl Tr + PointeeSized` + = help: the nightly-only, unstable trait `MetaSized` is not implemented for `impl Tr + PointeeSized` note: required by a bound in `Box` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL @@ -32,7 +32,7 @@ error[E0277]: the size for values of type `impl Tr + PointeeSized` cannot be kno LL | let x = pointeesized(); | ^^^^^^^^^^^^^^ doesn't have a known size | - = help: the trait `MetaSized` is not implemented for `impl Tr + PointeeSized` + = help: the nightly-only, unstable trait `MetaSized` is not implemented for `impl Tr + PointeeSized` note: required by a bound in `Box` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL @@ -51,7 +51,7 @@ error[E0277]: the size for values of type `impl Tr + PointeeSized` cannot be kno LL | let y: Box = x; | ^ doesn't have a known size | - = help: the trait `MetaSized` is not implemented for `impl Tr + PointeeSized` + = help: the nightly-only, unstable trait `MetaSized` is not implemented for `impl Tr + PointeeSized` = note: required for the cast from `Box` to `Box` error: aborting due to 6 previous errors diff --git a/tests/ui/specialization/issue-44861.stderr b/tests/ui/specialization/issue-44861.stderr index d184c4468b685..e480f65333fda 100644 --- a/tests/ui/specialization/issue-44861.stderr +++ b/tests/ui/specialization/issue-44861.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `(): CoerceUnsized<*const [u8]>` is not satisfied --> $DIR/issue-44861.rs:21:26 | LL | default type Data2 = (); - | ^^ the trait `CoerceUnsized<*const [u8]>` is not implemented for `()` + | ^^ the nightly-only, unstable trait `CoerceUnsized<*const [u8]>` is not implemented for `()` | note: required by a bound in `Smartass::Data2` --> $DIR/issue-44861.rs:12:17 diff --git a/tests/ui/suggestions/fn-trait-notation.stderr b/tests/ui/suggestions/fn-trait-notation.stderr index 9d0845478527b..ef7d5fe362820 100644 --- a/tests/ui/suggestions/fn-trait-notation.stderr +++ b/tests/ui/suggestions/fn-trait-notation.stderr @@ -32,7 +32,7 @@ error[E0059]: type parameter to bare `Fn` trait must be a tuple --> $DIR/fn-trait-notation.rs:4:8 | LL | F: Fn, - | ^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `i32` + | ^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `i32` | note: required by a bound in `Fn` --> $SRC_DIR/core/src/ops/function.rs:LL:COL @@ -47,7 +47,7 @@ error[E0277]: `i32` is not a tuple --> $DIR/fn-trait-notation.rs:9:5 | LL | f(3); - | ^^^^ the trait `std::marker::Tuple` is not implemented for `i32` + | ^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `i32` error[E0308]: mismatched types --> $DIR/fn-trait-notation.rs:17:5 diff --git a/tests/ui/suggestions/issue-72766.stderr b/tests/ui/suggestions/issue-72766.stderr index f0680dfe19f7e..03aad995b9666 100644 --- a/tests/ui/suggestions/issue-72766.stderr +++ b/tests/ui/suggestions/issue-72766.stderr @@ -4,7 +4,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | SadGirl {}.call()?; | ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future>` | - = help: the trait `Try` is not implemented for `impl Future>` + = help: the nightly-only, unstable trait `Try` is not implemented for `impl Future>` help: consider `await`ing on the `Future` | LL | SadGirl {}.call().await?; diff --git a/tests/ui/suggestions/issue-97704.stderr b/tests/ui/suggestions/issue-97704.stderr index a7284db1d9569..e20c68057eb7e 100644 --- a/tests/ui/suggestions/issue-97704.stderr +++ b/tests/ui/suggestions/issue-97704.stderr @@ -4,7 +4,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | func(async { Ok::<_, i32>(()) })?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future>` | - = help: the trait `Try` is not implemented for `impl Future>` + = help: the nightly-only, unstable trait `Try` is not implemented for `impl Future>` help: consider `await`ing on the `Future` | LL | func(async { Ok::<_, i32>(()) }).await?; diff --git a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr index dfa47f2ab4682..6df61e7bd1def 100644 --- a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr +++ b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Unstable` is not satisfied --> $DIR/unstable-trait-suggestion.rs:13:9 | LL | foo(t) - | --- ^ the trait `Unstable` is not implemented for `T` + | --- ^ the nightly-only, unstable trait `Unstable` is not implemented for `T` | | | required by a bound introduced by this call | @@ -20,7 +20,7 @@ error[E0277]: the trait bound `T: Step` is not satisfied --> $DIR/unstable-trait-suggestion.rs:17:14 | LL | for _ in t {} - | ^ the trait `Step` is not implemented for `T` + | ^ the nightly-only, unstable trait `Step` is not implemented for `T` | = note: required for `std::ops::Range` to implement `Iterator` = note: required for `std::ops::Range` to implement `IntoIterator` diff --git a/tests/ui/traits/issue-71036.rs b/tests/ui/traits/issue-71036.rs index 69eed0c0462fd..9593503240b25 100644 --- a/tests/ui/traits/issue-71036.rs +++ b/tests/ui/traits/issue-71036.rs @@ -10,7 +10,7 @@ struct Foo<'a, T: ?Sized> { impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn> for Foo<'a, T> {} //~^ ERROR the trait bound `&'a T: Unsize<&'a U>` is not satisfied -//~| NOTE the trait `Unsize<&'a U>` is not implemented for `&'a T` +//~| NOTE the nightly-only, unstable trait `Unsize<&'a U>` is not implemented for `&'a T` //~| NOTE all implementations of `Unsize` are provided automatically by the compiler //~| NOTE required for diff --git a/tests/ui/traits/issue-71036.stderr b/tests/ui/traits/issue-71036.stderr index 2452731f19f16..d2d88584f104e 100644 --- a/tests/ui/traits/issue-71036.stderr +++ b/tests/ui/traits/issue-71036.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'a T: Unsize<&'a U>` is not satisfied --> $DIR/issue-71036.rs:11:1 | LL | impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn> for Foo<'a, T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Unsize<&'a U>` is not implemented for `&'a T` | = note: all implementations of `Unsize` are provided automatically by the compiler, see for more information = note: required for `&'a &'a T` to implement `DispatchFromDyn<&'a &'a U>` diff --git a/tests/ui/traits/next-solver/coroutine.fail.stderr b/tests/ui/traits/next-solver/coroutine.fail.stderr index 8c263e8644bd0..a289e9839b23e 100644 --- a/tests/ui/traits/next-solver/coroutine.fail.stderr +++ b/tests/ui/traits/next-solver/coroutine.fail.stderr @@ -8,7 +8,7 @@ LL | / || { LL | | LL | | yield (); LL | | }, - | |_________^ the trait `Coroutine` is not implemented for `{coroutine@$DIR/coroutine.rs:20:9: 20:11}` + | |_________^ the nightly-only, unstable trait `Coroutine` is not implemented for `{coroutine@$DIR/coroutine.rs:20:9: 20:11}` | note: required by a bound in `needs_coroutine` --> $DIR/coroutine.rs:14:28 diff --git a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.next.stderr b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.next.stderr index 392680aa50643..1087fac50fd05 100644 --- a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.next.stderr +++ b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.next.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&dyn for<'a> Subtrait<'a, 'a>: CoerceUnsized<&dyn --> $DIR/higher-ranked-upcasting-ub.rs:22:5 | LL | x - | ^ the trait `Unsize Supertrait<'a, 'b>>` is not implemented for `dyn for<'a> Subtrait<'a, 'a>` + | ^ the nightly-only, unstable trait `Unsize Supertrait<'a, 'b>>` is not implemented for `dyn for<'a> Subtrait<'a, 'a>` | = note: all implementations of `Unsize` are provided automatically by the compiler, see for more information = note: required for `&dyn for<'a> Subtrait<'a, 'a>` to implement `CoerceUnsized<&dyn for<'a, 'b> Supertrait<'a, 'b>>` diff --git a/tests/ui/traits/unsize-goal-escaping-bounds.current.stderr b/tests/ui/traits/unsize-goal-escaping-bounds.current.stderr index e63a0bf50b7aa..d2d679243ee7c 100644 --- a/tests/ui/traits/unsize-goal-escaping-bounds.current.stderr +++ b/tests/ui/traits/unsize-goal-escaping-bounds.current.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'a> (): Unsize<(dyn Trait + 'a)>` is not sati --> $DIR/unsize-goal-escaping-bounds.rs:20:5 | LL | foo(); - | ^^^^^ the trait `for<'a> Unsize<(dyn Trait + 'a)>` is not implemented for `()` + | ^^^^^ the nightly-only, unstable trait `for<'a> Unsize<(dyn Trait + 'a)>` is not implemented for `()` | = note: all implementations of `Unsize` are provided automatically by the compiler, see for more information note: required by a bound in `foo` diff --git a/tests/ui/transmutability/assoc-bound.stderr b/tests/ui/transmutability/assoc-bound.stderr index 4dff24e2002aa..66a81f353815b 100644 --- a/tests/ui/transmutability/assoc-bound.stderr +++ b/tests/ui/transmutability/assoc-bound.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `::AssocA: TransmuteFrom<(), Assume { alig LL | type AssocB = T::AssocA; | ^^^^^^^^^ unsatisfied trait bound | - = help: the trait `TransmuteFrom<(), Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `::AssocA` + = help: the nightly-only, unstable trait `TransmuteFrom<(), Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `::AssocA` note: required by a bound in `B::AssocB` --> $DIR/assoc-bound.rs:9:18 | 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 6cb6a85c78a6b..6f7e9e1bfa33c 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 @@ -17,7 +17,7 @@ error[E0277]: the trait bound `(): TransmuteFrom<(), { Assume::SAFETY }>` is not --> $DIR/dont-assume-err-is-yes-issue-126377.rs:14:23 | LL | is_transmutable::<{}>(); - | ^^ the trait `TransmuteFrom<(), { Assume::SAFETY }>` is not implemented for `()` + | ^^ the nightly-only, unstable trait `TransmuteFrom<(), { Assume::SAFETY }>` is not implemented for `()` | note: required by a bound in `is_transmutable` --> $DIR/dont-assume-err-is-yes-issue-126377.rs:9:9 diff --git a/tests/ui/transmutability/references/unsafecell.stderr b/tests/ui/transmutability/references/unsafecell.stderr index 02a0935e84eae..85d6724b03fad 100644 --- a/tests/ui/transmutability/references/unsafecell.stderr +++ b/tests/ui/transmutability/references/unsafecell.stderr @@ -2,7 +2,7 @@ error[E0277]: `&u8` cannot be safely transmuted into `&UnsafeCell` --> $DIR/unsafecell.rs:27:50 | LL | assert::is_maybe_transmutable::<&'static u8, &'static UnsafeCell>(); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell` + | ^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Freeze` is not implemented for `UnsafeCell` | note: required by a bound in `is_maybe_transmutable` --> $DIR/unsafecell.rs:12:14 @@ -17,7 +17,7 @@ error[E0277]: `&UnsafeCell` cannot be safely transmuted into `&UnsafeCell $DIR/unsafecell.rs:29:62 | LL | assert::is_maybe_transmutable::<&'static UnsafeCell, &'static UnsafeCell>(); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell` + | ^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Freeze` is not implemented for `UnsafeCell` | note: required by a bound in `is_maybe_transmutable` --> $DIR/unsafecell.rs:12:14 @@ -32,7 +32,7 @@ error[E0277]: `&mut bool` cannot be safely transmuted into `&UnsafeCell` --> $DIR/unsafecell.rs:45:56 | LL | assert::is_maybe_transmutable::<&'static mut bool, &'static UnsafeCell>(); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell` + | ^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Freeze` is not implemented for `UnsafeCell` | note: required by a bound in `is_maybe_transmutable` --> $DIR/unsafecell.rs:12:14 @@ -47,7 +47,7 @@ error[E0277]: `&mut UnsafeCell` cannot be safely transmuted into `&UnsafeC --> $DIR/unsafecell.rs:46:68 | LL | assert::is_maybe_transmutable::<&'static mut UnsafeCell, &'static UnsafeCell>(); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell` + | ^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Freeze` is not implemented for `UnsafeCell` | note: required by a bound in `is_maybe_transmutable` --> $DIR/unsafecell.rs:12:14 diff --git a/tests/ui/try-block/try-block-bad-type-heterogeneous.stderr b/tests/ui/try-block/try-block-bad-type-heterogeneous.stderr index 7c7cedd392e64..4962534cf2945 100644 --- a/tests/ui/try-block/try-block-bad-type-heterogeneous.stderr +++ b/tests/ui/try-block/try-block-bad-type-heterogeneous.stderr @@ -30,7 +30,7 @@ error[E0277]: a `try` block must return `Result` or `Option` (or another type th LL | let res = try bikeshed () { }; | ^ could not wrap the final value of the block as `()` doesn't implement `Try` | - = help: the trait `Try` is not implemented for `()` + = help: the nightly-only, unstable trait `Try` is not implemented for `()` error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`) --> $DIR/try-block-bad-type-heterogeneous.rs:20:34 @@ -38,7 +38,7 @@ error[E0277]: a `try` block must return `Result` or `Option` (or another type th LL | let res = try bikeshed i32 { 5 }; | ^ could not wrap the final value of the block as `i32` doesn't implement `Try` | - = help: the trait `Try` is not implemented for `i32` + = help: the nightly-only, unstable trait `Try` is not implemented for `i32` error: aborting due to 5 previous errors diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr index 9df01a4cf5b16..6f806da088b60 100644 --- a/tests/ui/try-block/try-block-bad-type.stderr +++ b/tests/ui/try-block/try-block-bad-type.stderr @@ -29,7 +29,7 @@ error[E0277]: a `try` block must return `Result` or `Option` (or another type th LL | let res: () = try { }; | ^ could not wrap the final value of the block as `()` doesn't implement `Try` | - = help: the trait `Try` is not implemented for `()` + = help: the nightly-only, unstable trait `Try` is not implemented for `()` error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`) --> $DIR/try-block-bad-type.rs:20:26 @@ -37,7 +37,7 @@ error[E0277]: a `try` block must return `Result` or `Option` (or another type th LL | let res: i32 = try { 5 }; | ^ could not wrap the final value of the block as `i32` doesn't implement `Try` | - = help: the trait `Try` is not implemented for `i32` + = help: the nightly-only, unstable trait `Try` is not implemented for `i32` error: aborting due to 5 previous errors diff --git a/tests/ui/try-block/try-block-in-while.stderr b/tests/ui/try-block/try-block-in-while.stderr index 2760e930102b4..6d6917362bc7d 100644 --- a/tests/ui/try-block/try-block-in-while.stderr +++ b/tests/ui/try-block/try-block-in-while.stderr @@ -4,7 +4,7 @@ error[E0277]: a `try` block must return `Result` or `Option` (or another type th LL | while try { false } {} | ^^^^^ could not wrap the final value of the block as `bool` doesn't implement `Try` | - = help: the trait `Try` is not implemented for `bool` + = help: the nightly-only, unstable trait `Try` is not implemented for `bool` error: aborting due to 1 previous error diff --git a/tests/ui/try-trait/try-operator-on-main.stderr b/tests/ui/try-trait/try-operator-on-main.stderr index 9c2526442ab5b..d58720638aec1 100644 --- a/tests/ui/try-trait/try-operator-on-main.stderr +++ b/tests/ui/try-trait/try-operator-on-main.stderr @@ -22,7 +22,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | - = help: the trait `Try` is not implemented for `()` + = help: the nightly-only, unstable trait `Try` is not implemented for `()` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-operator-on-main.rs:10:7 @@ -37,7 +37,7 @@ error[E0277]: the trait bound `(): Try` is not satisfied --> $DIR/try-operator-on-main.rs:14:25 | LL | try_trait_generic::<()>(); - | ^^ the trait `Try` is not implemented for `()` + | ^^ the nightly-only, unstable trait `Try` is not implemented for `()` | note: required by a bound in `try_trait_generic` --> $DIR/try-operator-on-main.rs:17:25 @@ -51,7 +51,7 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | - = help: the trait `Try` is not implemented for `()` + = help: the nightly-only, unstable trait `Try` is not implemented for `()` error: aborting due to 5 previous errors diff --git a/tests/ui/tuple/builtin-fail.stderr b/tests/ui/tuple/builtin-fail.stderr index 0dec88ded7ce2..5e84dbff454d7 100644 --- a/tests/ui/tuple/builtin-fail.stderr +++ b/tests/ui/tuple/builtin-fail.stderr @@ -2,7 +2,7 @@ error[E0277]: `T` is not a tuple --> $DIR/builtin-fail.rs:8:23 | LL | assert_is_tuple::(); - | ^ the trait `std::marker::Tuple` is not implemented for `T` + | ^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `T` | note: required by a bound in `assert_is_tuple` --> $DIR/builtin-fail.rs:3:23 @@ -18,7 +18,7 @@ error[E0277]: `i32` is not a tuple --> $DIR/builtin-fail.rs:13:23 | LL | assert_is_tuple::(); - | ^^^ the trait `std::marker::Tuple` is not implemented for `i32` + | ^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `i32` | note: required by a bound in `assert_is_tuple` --> $DIR/builtin-fail.rs:3:23 @@ -30,7 +30,7 @@ error[E0277]: `i32` is not a tuple --> $DIR/builtin-fail.rs:15:24 | LL | assert_is_tuple::<(i32)>(); - | ^^^ the trait `std::marker::Tuple` is not implemented for `i32` + | ^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `i32` | note: required by a bound in `assert_is_tuple` --> $DIR/builtin-fail.rs:3:23 @@ -44,7 +44,7 @@ error[E0277]: `TupleStruct` is not a tuple LL | assert_is_tuple::(); | ^^^^^^^^^^^ unsatisfied trait bound | -help: the trait `std::marker::Tuple` is not implemented for `TupleStruct` +help: the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `TupleStruct` --> $DIR/builtin-fail.rs:5:1 | LL | struct TupleStruct(i32, i32); diff --git a/tests/ui/type/pattern_types/nested.stderr b/tests/ui/type/pattern_types/nested.stderr index bb206d9db3db8..7893cc8492484 100644 --- a/tests/ui/type/pattern_types/nested.stderr +++ b/tests/ui/type/pattern_types/nested.stderr @@ -13,7 +13,7 @@ error[E0277]: `(u32) is 1..` is not a valid base type for range patterns LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ only integer types and `char` are supported | - = help: the trait `core::pat::RangePattern` is not implemented for `(u32) is 1..` + = help: the nightly-only, unstable trait `core::pat::RangePattern` is not implemented for `(u32) is 1..` = help: the following other types implement trait `core::pat::RangePattern`: char i128 @@ -31,7 +31,7 @@ error[E0277]: `(i32) is 1..` is not a valid base type for range patterns LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ only integer types and `char` are supported | - = help: the trait `core::pat::RangePattern` is not implemented for `(i32) is 1..` + = help: the nightly-only, unstable trait `core::pat::RangePattern` is not implemented for `(i32) is 1..` = help: the following other types implement trait `core::pat::RangePattern`: char i128 @@ -55,7 +55,7 @@ error[E0277]: `(i32) is 1..` is not a valid base type for range patterns LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ only integer types and `char` are supported | - = help: the trait `core::pat::RangePattern` is not implemented for `(i32) is 1..` + = help: the nightly-only, unstable trait `core::pat::RangePattern` is not implemented for `(i32) is 1..` = help: the following other types implement trait `core::pat::RangePattern`: char i128 @@ -92,7 +92,7 @@ error[E0277]: `(i32) is 1..` is not a valid base type for range patterns LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); | ^ only integer types and `char` are supported | - = help: the trait `core::pat::RangePattern` is not implemented for `(i32) is 1..` + = help: the nightly-only, unstable trait `core::pat::RangePattern` is not implemented for `(i32) is 1..` = help: the following other types implement trait `core::pat::RangePattern`: char i128 @@ -110,7 +110,7 @@ error[E0277]: `()` is not a valid base type for range patterns LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); | ^^ only integer types and `char` are supported | - = help: the trait `core::pat::RangePattern` is not implemented for `()` + = help: the nightly-only, unstable trait `core::pat::RangePattern` is not implemented for `()` = help: the following other types implement trait `core::pat::RangePattern`: char i128 @@ -145,7 +145,7 @@ error[E0277]: `()` is not a valid base type for range patterns LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); | ^ only integer types and `char` are supported | - = help: the trait `core::pat::RangePattern` is not implemented for `()` + = help: the nightly-only, unstable trait `core::pat::RangePattern` is not implemented for `()` = help: the following other types implement trait `core::pat::RangePattern`: char i128 @@ -163,7 +163,7 @@ error[E0277]: `f32` is not a valid base type for range patterns LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!(); | ^^^ only integer types and `char` are supported | - = help: the trait `core::pat::RangePattern` is not implemented for `f32` + = help: the nightly-only, unstable trait `core::pat::RangePattern` is not implemented for `f32` = help: the following other types implement trait `core::pat::RangePattern`: i128 i16 diff --git a/tests/ui/typeck/issue-57404.stderr b/tests/ui/typeck/issue-57404.stderr index f1d28e475a072..7f8a99ebb917d 100644 --- a/tests/ui/typeck/issue-57404.stderr +++ b/tests/ui/typeck/issue-57404.stderr @@ -2,7 +2,7 @@ error[E0277]: `&mut ()` is not a tuple --> $DIR/issue-57404.rs:6:41 | LL | handlers.unwrap().as_mut().call_mut(&mut ()); - | -------- ^^^^^^^ the trait `std::marker::Tuple` is not implemented for `&mut ()` + | -------- ^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `&mut ()` | | | required by a bound introduced by this call | diff --git a/tests/ui/unboxed-closures/non-tupled-arg-mismatch.stderr b/tests/ui/unboxed-closures/non-tupled-arg-mismatch.stderr index 621a533dd1c5c..488dff646793c 100644 --- a/tests/ui/unboxed-closures/non-tupled-arg-mismatch.stderr +++ b/tests/ui/unboxed-closures/non-tupled-arg-mismatch.stderr @@ -2,7 +2,7 @@ error[E0059]: type parameter to bare `Fn` trait must be a tuple --> $DIR/non-tupled-arg-mismatch.rs:3:9 | LL | fn a>(f: F) {} - | ^^^^^^^^^ the trait `std::marker::Tuple` is not implemented for `usize` + | ^^^^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `usize` | note: required by a bound in `Fn` --> $SRC_DIR/core/src/ops/function.rs:LL:COL From 89713fcef5b36e92db77bfea40378252607edf67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 12 Jan 2026 23:05:08 +0000 Subject: [PATCH 08/27] Mention `Range` when `Step` trait bound is unmet --- library/core/src/iter/range.rs | 5 +++++ tests/ui/range/range-1.stderr | 1 + tests/ui/trait-bounds/unstable-trait-suggestion.stderr | 1 + 3 files changed, 7 insertions(+) diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 9e43d5688cecc..39e218a5f4b3c 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -21,6 +21,11 @@ unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u6 /// The *successor* operation moves towards values that compare greater. /// The *predecessor* operation moves towards values that compare lesser. #[rustc_diagnostic_item = "range_step"] +#[rustc_on_unimplemented( + note = "`Range` only implements `Iterator` for select types in the standard library, \ + particularly integers; to see the full list of types, see the documentation for the \ + unstable `Step` trait" +)] #[unstable(feature = "step_trait", issue = "42168")] pub trait Step: Clone + PartialOrd + Sized { /// Returns the bounds on the number of *successor* steps required to get from `start` to `end` diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr index f2d603b32af0a..a5001a70eae65 100644 --- a/tests/ui/range/range-1.stderr +++ b/tests/ui/range/range-1.stderr @@ -10,6 +10,7 @@ error[E0277]: the trait bound `bool: Step` is not satisfied LL | for i in false..true {} | ^^^^^^^^^^^ the nightly-only, unstable trait `Step` is not implemented for `bool` | + = note: `Range` only implements `Iterator` for select types in the standard library, particularly integers; to see the full list of types, see the documentation for the unstable `Step` trait = note: required for `std::ops::Range` to implement `Iterator` = note: required for `std::ops::Range` to implement `IntoIterator` diff --git a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr index 6df61e7bd1def..5820074b41cc2 100644 --- a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr +++ b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr @@ -22,6 +22,7 @@ error[E0277]: the trait bound `T: Step` is not satisfied LL | for _ in t {} | ^ the nightly-only, unstable trait `Step` is not implemented for `T` | + = note: `Range` only implements `Iterator` for select types in the standard library, particularly integers; to see the full list of types, see the documentation for the unstable `Step` trait = note: required for `std::ops::Range` to implement `Iterator` = note: required for `std::ops::Range` to implement `IntoIterator` help: consider restricting type parameter `T` with unstable trait `Step` From 45edce26d36b4d05e350c7b75419159e7f750e5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 13 Jan 2026 01:28:28 +0000 Subject: [PATCH 09/27] Update rustc_on_unimplemented message for `Step` --- library/core/src/iter/range.rs | 1 + tests/ui/range/range-1.rs | 2 +- tests/ui/range/range-1.stderr | 2 +- tests/ui/trait-bounds/unstable-trait-suggestion.stderr | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 39e218a5f4b3c..0be1e8699bf58 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -22,6 +22,7 @@ unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u6 /// The *predecessor* operation moves towards values that compare lesser. #[rustc_diagnostic_item = "range_step"] #[rustc_on_unimplemented( + message = "`std::ops::Range<{Self}>` is not an iterator", note = "`Range` only implements `Iterator` for select types in the standard library, \ particularly integers; to see the full list of types, see the documentation for the \ unstable `Step` trait" diff --git a/tests/ui/range/range-1.rs b/tests/ui/range/range-1.rs index 192426fe228fe..8fbfae55b8a67 100644 --- a/tests/ui/range/range-1.rs +++ b/tests/ui/range/range-1.rs @@ -7,7 +7,7 @@ pub fn main() { // Bool => does not implement iterator. for i in false..true {} - //~^ ERROR `bool: Step` is not satisfied + //~^ ERROR `std::ops::Range` is not an iterator // Unsized type. let arr: &[_] = &[1, 2, 3]; diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr index a5001a70eae65..5491d06aee092 100644 --- a/tests/ui/range/range-1.stderr +++ b/tests/ui/range/range-1.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let _ = 0u32..10i32; | ^^^^^ expected `u32`, found `i32` -error[E0277]: the trait bound `bool: Step` is not satisfied +error[E0277]: `std::ops::Range` is not an iterator --> $DIR/range-1.rs:9:14 | LL | for i in false..true {} diff --git a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr index 5820074b41cc2..011e56044bfec 100644 --- a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr +++ b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr @@ -16,7 +16,7 @@ help: consider restricting type parameter `T` with unstable trait `Unstable` LL | pub fn bar(t: T) { | ++++++++++ -error[E0277]: the trait bound `T: Step` is not satisfied +error[E0277]: `std::ops::Range` is not an iterator --> $DIR/unstable-trait-suggestion.rs:17:14 | LL | for _ in t {} From 37afa310c907250468ff8cf66d9916ab956a1dac Mon Sep 17 00:00:00 2001 From: mu001999 Date: Sat, 10 Jan 2026 17:06:21 +0800 Subject: [PATCH 10/27] Remove all usage of FeedConstTy::No --- .../src/hir_ty_lowering/bounds.rs | 34 +++++----- .../src/hir_ty_lowering/mod.rs | 53 ++++++++++++--- compiler/rustc_hir_typeck/src/expr.rs | 5 +- src/librustdoc/clean/mod.rs | 68 ++++++++++++++++--- 4 files changed, 124 insertions(+), 36 deletions(-) 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 72d21371f66cc..0a874b881801d 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -510,7 +510,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Create the generic arguments for the associated type or constant by joining the // parent arguments (the arguments of the trait) and the own arguments (the ones of // the associated item itself) and construct an alias type using them. - let alias_term = candidate.map_bound(|trait_ref| { + candidate.map_bound(|trait_ref| { let item_segment = hir::PathSegment { ident: constraint.ident, hir_id: constraint.hir_id, @@ -528,20 +528,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(?alias_args); ty::AliasTerm::new_from_args(tcx, assoc_item.def_id, alias_args) - }); - - // Provide the resolved type of the associated constant to `type_of(AnonConst)`. - if let Some(const_arg) = constraint.ct() - && let hir::ConstArgKind::Anon(anon_const) = const_arg.kind - { - let ty = alias_term - .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args)); - let ty = - check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id); - tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty)); - } - - alias_term + }) }; match constraint.kind { @@ -555,7 +542,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::AssocItemConstraintKind::Equality { term } => { let term = match term { hir::Term::Ty(ty) => self.lower_ty(ty).into(), - hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(), + hir::Term::Const(ct) => { + // Provide the resolved type of the associated constant + let ty = projection_term.map_bound(|alias| { + tcx.type_of(alias.def_id).instantiate(tcx, alias.args) + }); + let ty = check_assoc_const_binding_type( + self, + constraint.ident, + ty, + constraint.hir_id, + ); + + self.lower_const_arg(ct, FeedConstTy::WithTy(ty)).into() + } }; // Find any late-bound regions declared in `ty` that are not @@ -871,7 +871,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// probably gate this behind another feature flag. /// /// [^1]: . -fn check_assoc_const_binding_type<'tcx>( +pub(crate) fn check_assoc_const_binding_type<'tcx>( cx: &dyn HirTyLowerer<'tcx>, assoc_const: Ident, ty: ty::Binder<'tcx, Ty<'tcx>>, 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 d2cbf89336d8b..be5ac21e2ca84 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1269,10 +1269,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut where_bounds = vec![]; for bound in [bound, bound2].into_iter().chain(matching_candidates) { let bound_id = bound.def_id(); - let bound_span = tcx - .associated_items(bound_id) - .find_by_ident_and_kind(tcx, assoc_ident, assoc_tag, bound_id) - .and_then(|item| tcx.hir_span_if_local(item.def_id)); + let assoc_item = tcx.associated_items(bound_id).find_by_ident_and_kind( + tcx, + assoc_ident, + assoc_tag, + bound_id, + ); + let bound_span = assoc_item.and_then(|item| tcx.hir_span_if_local(item.def_id)); if let Some(bound_span) = bound_span { err.span_label( @@ -1285,7 +1288,41 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let term: ty::Term<'_> = match term { hir::Term::Ty(ty) => self.lower_ty(ty).into(), hir::Term::Const(ct) => { - self.lower_const_arg(ct, FeedConstTy::No).into() + let assoc_item = + assoc_item.expect("assoc_item should be present"); + let projection_term = bound.map_bound(|trait_ref| { + let item_segment = hir::PathSegment { + ident: constraint.ident, + hir_id: constraint.hir_id, + res: Res::Err, + args: Some(constraint.gen_args), + infer_args: false, + }; + + let alias_args = self.lower_generic_args_of_assoc_item( + constraint.ident.span, + assoc_item.def_id, + &item_segment, + trait_ref.args, + ); + ty::AliasTerm::new_from_args( + tcx, + assoc_item.def_id, + alias_args, + ) + }); + + let ty = projection_term.map_bound(|alias| { + tcx.type_of(alias.def_id).instantiate(tcx, alias.args) + }); + let ty = bounds::check_assoc_const_binding_type( + self, + constraint.ident, + ty, + constraint.hir_id, + ); + + self.lower_const_arg(ct, FeedConstTy::WithTy(ty)).into() } }; if term.references_error() { @@ -2993,7 +3030,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) } hir::TyKind::Array(ty, length) => { - let length = self.lower_const_arg(length, FeedConstTy::No); + let length = self.lower_const_arg(length, FeedConstTy::WithTy(tcx.types.usize)); Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length) } hir::TyKind::Infer(()) => { @@ -3033,8 +3070,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Keep this list of types in sync with the list of types that // the `RangePattern` trait is implemented for. ty::Int(_) | ty::Uint(_) | ty::Char => { - let start = self.lower_const_arg(start, FeedConstTy::No); - let end = self.lower_const_arg(end, FeedConstTy::No); + let start = self.lower_const_arg(start, FeedConstTy::WithTy(ty)); + let end = self.lower_const_arg(end, FeedConstTy::WithTy(ty)); Ok(ty::PatternKind::Range { start, end }) } _ => Err(self diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 9d7e09b020a75..d7366887d85c9 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1749,7 +1749,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let count_span = count.span; let count = self.try_structurally_resolve_const( count_span, - self.normalize(count_span, self.lower_const_arg(count, FeedConstTy::No)), + self.normalize( + count_span, + self.lower_const_arg(count, FeedConstTy::WithTy(tcx.types.usize)), + ), ); if let Some(count) = count.try_to_target_usize(tcx) { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 597a85f397695..c93778ec8f0af 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -469,11 +469,23 @@ fn clean_middle_term<'tcx>( } } -fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term { +fn clean_hir_term<'tcx>( + assoc_item: Option, + term: &hir::Term<'tcx>, + span: rustc_span::Span, + cx: &mut DocContext<'tcx>, +) -> Term { match term { hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)), hir::Term::Const(c) => { - let ct = lower_const_arg_for_rustdoc(cx.tcx, c, FeedConstTy::No); + let ty = if let Some(assoc_item) = assoc_item { + // FIXME(generic_const_items): this should instantiate with the alias item's args + cx.tcx.type_of(assoc_item).instantiate_identity() + } else { + Ty::new_error_with_message(cx.tcx, span, "cannot find the associated constant") + }; + + let ct = lower_const_arg_for_rustdoc(cx.tcx, c, FeedConstTy::WithTy(ty)); Term::Constant(clean_middle_const(ty::Binder::dummy(ct), cx)) } } @@ -650,7 +662,14 @@ fn clean_generic_param<'tcx>( GenericParamDefKind::Const { ty: Box::new(clean_ty(ty, cx)), default: default.map(|ct| { - Box::new(lower_const_arg_for_rustdoc(cx.tcx, ct, FeedConstTy::No).to_string()) + Box::new( + lower_const_arg_for_rustdoc( + cx.tcx, + ct, + FeedConstTy::WithTy(lower_ty(cx.tcx, ty)), + ) + .to_string(), + ) }), }, ), @@ -1531,7 +1550,7 @@ fn first_non_private_clean_path<'tcx>( && path_last.args.is_some() { assert!(new_path_last.args.is_empty()); - new_path_last.args = clean_generic_args(path_last_args, cx); + new_path_last.args = clean_generic_args(None, path_last_args, cx); } new_clean_path } @@ -1812,7 +1831,11 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T let length = match const_arg.kind { hir::ConstArgKind::Infer(..) | hir::ConstArgKind::Error(..) => "_".to_string(), hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) => { - let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No); + let ct = lower_const_arg_for_rustdoc( + cx.tcx, + const_arg, + FeedConstTy::WithTy(cx.tcx.types.usize), + ); let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id); let ct = cx.tcx.normalize_erasing_regions(typing_env, ct); print_const(cx, ct) @@ -1823,7 +1846,11 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T | hir::ConstArgKind::Tup(..) | hir::ConstArgKind::Array(..) | hir::ConstArgKind::Literal(..) => { - let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No); + let ct = lower_const_arg_for_rustdoc( + cx.tcx, + const_arg, + FeedConstTy::WithTy(cx.tcx.types.usize), + ); print_const(cx, ct) } }; @@ -2516,6 +2543,7 @@ fn clean_path<'tcx>(path: &hir::Path<'tcx>, cx: &mut DocContext<'tcx>) -> Path { } fn clean_generic_args<'tcx>( + trait_did: Option, generic_args: &hir::GenericArgs<'tcx>, cx: &mut DocContext<'tcx>, ) -> GenericArgs { @@ -2539,7 +2567,13 @@ fn clean_generic_args<'tcx>( let constraints = generic_args .constraints .iter() - .map(|c| clean_assoc_item_constraint(c, cx)) + .map(|c| { + clean_assoc_item_constraint( + trait_did.expect("only trait ref has constraints"), + c, + cx, + ) + }) .collect::>(); GenericArgs::AngleBracketed { args, constraints } } @@ -2562,7 +2596,9 @@ fn clean_path_segment<'tcx>( path: &hir::PathSegment<'tcx>, cx: &mut DocContext<'tcx>, ) -> PathSegment { - PathSegment { name: path.ident.name, args: clean_generic_args(path.args(), cx) } + let trait_did = + if let hir::def::Res::Def(DefKind::Trait, did) = path.res { Some(did) } else { None }; + PathSegment { name: path.ident.name, args: clean_generic_args(trait_did, path.args(), cx) } } fn clean_bare_fn_ty<'tcx>( @@ -3126,17 +3162,29 @@ fn clean_maybe_renamed_foreign_item<'tcx>( } fn clean_assoc_item_constraint<'tcx>( + trait_did: DefId, constraint: &hir::AssocItemConstraint<'tcx>, cx: &mut DocContext<'tcx>, ) -> AssocItemConstraint { AssocItemConstraint { assoc: PathSegment { name: constraint.ident.name, - args: clean_generic_args(constraint.gen_args, cx), + args: clean_generic_args(None, constraint.gen_args, cx), }, kind: match constraint.kind { hir::AssocItemConstraintKind::Equality { ref term } => { - AssocItemConstraintKind::Equality { term: clean_hir_term(term, cx) } + let assoc_tag = match term { + hir::Term::Ty(_) => ty::AssocTag::Type, + hir::Term::Const(_) => ty::AssocTag::Const, + }; + let assoc_item = cx + .tcx + .associated_items(trait_did) + .find_by_ident_and_kind(cx.tcx, constraint.ident, assoc_tag, trait_did) + .map(|item| item.def_id); + AssocItemConstraintKind::Equality { + term: clean_hir_term(assoc_item, term, constraint.span, cx), + } } hir::AssocItemConstraintKind::Bound { bounds } => AssocItemConstraintKind::Bound { bounds: bounds.iter().filter_map(|b| clean_generic_bound(b, cx)).collect(), From 6d837ae9c7660ce82d63af3b622c0fbb976b09cb Mon Sep 17 00:00:00 2001 From: mu001999 Date: Sun, 11 Jan 2026 18:43:25 +0800 Subject: [PATCH 11/27] Remove FeedConstTy --- compiler/rustc_hir_analysis/src/collect.rs | 8 +- .../src/hir_ty_lowering/bounds.rs | 5 +- .../src/hir_ty_lowering/mod.rs | 89 +++++-------------- compiler/rustc_hir_analysis/src/lib.rs | 6 +- compiler/rustc_hir_typeck/src/expr.rs | 7 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 13 +-- .../rustc_hir_typeck/src/method/confirm.rs | 7 +- src/librustdoc/clean/mod.rs | 22 +---- 8 files changed, 48 insertions(+), 109 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index bacdf0049806e..2c02534093870 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -47,9 +47,7 @@ use rustc_trait_selection::traits::{ use tracing::{debug, instrument}; use crate::errors; -use crate::hir_ty_lowering::{ - FeedConstTy, HirTyLowerer, InherentAssocCandidate, RegionInferReason, -}; +use crate::hir_ty_lowering::{HirTyLowerer, InherentAssocCandidate, RegionInferReason}; pub(crate) mod dump; mod generics_of; @@ -1499,7 +1497,7 @@ fn const_param_default<'tcx>( let ct = icx .lowerer() - .lower_const_arg(default_ct, FeedConstTy::with_type_of(tcx, def_id, identity_args)); + .lower_const_arg(default_ct, tcx.type_of(def_id).instantiate(tcx, identity_args)); ty::EarlyBinder::bind(ct) } @@ -1557,7 +1555,7 @@ fn const_of_item<'tcx>( let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id); let ct = icx .lowerer() - .lower_const_arg(ct_arg, FeedConstTy::with_type_of(tcx, def_id.to_def_id(), identity_args)); + .lower_const_arg(ct_arg, tcx.type_of(def_id.to_def_id()).instantiate(tcx, identity_args)); if let Err(e) = icx.check_tainted_by_errors() && !ct.references_error() { 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 0a874b881801d..d6441702b268c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -20,7 +20,7 @@ use tracing::{debug, instrument}; use crate::errors; use crate::hir_ty_lowering::{ - AssocItemQSelf, FeedConstTy, GenericsArgsErrExtend, HirTyLowerer, ImpliedBoundsContext, + AssocItemQSelf, GenericsArgsErrExtend, HirTyLowerer, ImpliedBoundsContext, OverlappingAsssocItemConstraints, PredicateFilter, RegionInferReason, }; @@ -543,7 +543,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let term = match term { hir::Term::Ty(ty) => self.lower_ty(ty).into(), hir::Term::Const(ct) => { - // Provide the resolved type of the associated constant let ty = projection_term.map_bound(|alias| { tcx.type_of(alias.def_id).instantiate(tcx, alias.args) }); @@ -554,7 +553,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { constraint.hir_id, ); - self.lower_const_arg(ct, FeedConstTy::WithTy(ty)).into() + self.lower_const_arg(ct, ty).into() } }; 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 be5ac21e2ca84..3dcc0232b301e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -253,35 +253,6 @@ impl AssocItemQSelf { } } -/// In some cases, [`hir::ConstArg`]s that are being used in the type system -/// through const generics need to have their type "fed" to them -/// using the query system. -/// -/// Use this enum with `::lower_const_arg` to instruct it with the -/// desired behavior. -#[derive(Debug, Clone, Copy)] -pub enum FeedConstTy<'tcx> { - /// Feed the type to the (anno) const arg. - WithTy(Ty<'tcx>), - /// Don't feed the type. - No, -} - -impl<'tcx> FeedConstTy<'tcx> { - /// The `DefId` belongs to the const param that we are supplying - /// this (anon) const arg to. - /// - /// The list of generic args is used to instantiate the parameters - /// used by the type of the const param specified by `DefId`. - pub fn with_type_of( - tcx: TyCtxt<'tcx>, - def_id: DefId, - generic_args: &[ty::GenericArg<'tcx>], - ) -> Self { - Self::WithTy(tcx.type_of(def_id).instantiate(tcx, generic_args)) - } -} - #[derive(Debug, Clone, Copy)] enum LowerTypeRelativePathMode { Type(PermitVariants), @@ -733,7 +704,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Ambig portions of `ConstArg` are handled in the match arm below .lower_const_arg( ct.as_unambig_ct(), - FeedConstTy::with_type_of(tcx, param.def_id, preceding_args), + tcx.type_of(param.def_id).instantiate(tcx, preceding_args), ) .into(), (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { @@ -1322,7 +1293,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { constraint.hir_id, ); - self.lower_const_arg(ct, FeedConstTy::WithTy(ty)).into() + self.lower_const_arg(ct, ty).into() } }; if term.references_error() { @@ -2347,16 +2318,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Lower a [`hir::ConstArg`] to a (type-level) [`ty::Const`](Const). #[instrument(skip(self), level = "debug")] - pub fn lower_const_arg( - &self, - const_arg: &hir::ConstArg<'tcx>, - feed: FeedConstTy<'tcx>, - ) -> Const<'tcx> { + pub fn lower_const_arg(&self, const_arg: &hir::ConstArg<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { let tcx = self.tcx(); - if let FeedConstTy::WithTy(anon_const_type) = feed - && let hir::ConstArgKind::Anon(anon) = &const_arg.kind - { + if let hir::ConstArgKind::Anon(anon) = &const_arg.kind { // FIXME(generic_const_parameter_types): Ideally we remove these errors below when // we have the ability to intermix typeck of anon const const args with the parent // bodies typeck. @@ -2366,7 +2331,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // hir typeck was using equality but mir borrowck wound up using subtyping as that could // result in a non-infer in hir typeck but a region variable in borrowck. if tcx.features().generic_const_parameter_types() - && (anon_const_type.has_free_regions() || anon_const_type.has_erased_regions()) + && (ty.has_free_regions() || ty.has_erased_regions()) { let e = self.dcx().span_err( const_arg.span, @@ -2378,7 +2343,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // We must error if the instantiated type has any inference variables as we will // use this type to feed the `type_of` and query results must not contain inference // variables otherwise we will ICE. - if anon_const_type.has_non_region_infer() { + if ty.has_non_region_infer() { let e = self.dcx().span_err( const_arg.span, "anonymous constants with inferred types are not yet supported", @@ -2388,7 +2353,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } // We error when the type contains unsubstituted generics since we do not currently // give the anon const any of the generics from the parent. - if anon_const_type.has_non_region_param() { + if ty.has_non_region_param() { let e = self.dcx().span_err( const_arg.span, "anonymous constants referencing generics are not yet supported", @@ -2397,12 +2362,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return ty::Const::new_error(tcx, e); } - tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(anon_const_type)); + tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(ty)); } let hir_id = const_arg.hir_id; match const_arg.kind { - hir::ConstArgKind::Tup(exprs) => self.lower_const_arg_tup(exprs, feed, const_arg.span), + hir::ConstArgKind::Tup(exprs) => self.lower_const_arg_tup(exprs, ty, const_arg.span), hir::ConstArgKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { debug!(?maybe_qself, ?path); let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself)); @@ -2426,16 +2391,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::ConstArgKind::TupleCall(qpath, args) => { self.lower_const_arg_tuple_call(hir_id, qpath, args, const_arg.span) } - hir::ConstArgKind::Array(array_expr) => self.lower_const_arg_array(array_expr, feed), + hir::ConstArgKind::Array(array_expr) => self.lower_const_arg_array(array_expr, ty), hir::ConstArgKind::Anon(anon) => self.lower_const_arg_anon(anon), hir::ConstArgKind::Infer(()) => self.ct_infer(None, const_arg.span), hir::ConstArgKind::Error(e) => ty::Const::new_error(tcx, e), - hir::ConstArgKind::Literal(kind) if let FeedConstTy::WithTy(anon_const_type) = feed => { - self.lower_const_arg_literal(&kind, anon_const_type, const_arg.span) - } - hir::ConstArgKind::Literal(..) => { - let e = self.dcx().span_err(const_arg.span, "literal of unknown type"); - ty::Const::new_error(tcx, e) + hir::ConstArgKind::Literal(kind) => { + self.lower_const_arg_literal(&kind, ty, const_arg.span) } } } @@ -2443,14 +2404,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn lower_const_arg_array( &self, array_expr: &'tcx hir::ConstArgArrayExpr<'tcx>, - feed: FeedConstTy<'tcx>, + ty: Ty<'tcx>, ) -> Const<'tcx> { let tcx = self.tcx(); - let FeedConstTy::WithTy(ty) = feed else { - return Const::new_error_with_message(tcx, array_expr.span, "unsupported const array"); - }; - let ty::Array(elem_ty, _) = ty.kind() else { return Const::new_error_with_message( tcx, @@ -2462,7 +2419,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let elems = array_expr .elems .iter() - .map(|elem| self.lower_const_arg(elem, FeedConstTy::WithTy(*elem_ty))) + .map(|elem| self.lower_const_arg(elem, *elem_ty)) .collect::>(); let valtree = ty::ValTree::from_branches(tcx, elems); @@ -2545,7 +2502,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .iter() .zip(args) .map(|(field_def, arg)| { - self.lower_const_arg(arg, FeedConstTy::with_type_of(tcx, field_def.did, adt_args)) + self.lower_const_arg(arg, tcx.type_of(field_def.did).instantiate(tcx, adt_args)) }) .collect::>(); @@ -2564,15 +2521,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn lower_const_arg_tup( &self, exprs: &'tcx [&'tcx hir::ConstArg<'tcx>], - feed: FeedConstTy<'tcx>, + ty: Ty<'tcx>, span: Span, ) -> Const<'tcx> { let tcx = self.tcx(); - let FeedConstTy::WithTy(ty) = feed else { - return Const::new_error_with_message(tcx, span, "const tuple lack type information"); - }; - let ty::Tuple(tys) = ty.kind() else { let e = tcx.dcx().span_err(span, format!("expected `{}`, found const tuple", ty)); return Const::new_error(tcx, e); @@ -2581,7 +2534,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let exprs = exprs .iter() .zip(tys.iter()) - .map(|(expr, ty)| self.lower_const_arg(expr, FeedConstTy::WithTy(ty))) + .map(|(expr, ty)| self.lower_const_arg(expr, ty)) .collect::>(); let valtree = ty::ValTree::from_branches(tcx, exprs); @@ -2668,7 +2621,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_const_arg( expr.expr, - FeedConstTy::with_type_of(tcx, field_def.did, adt_args), + tcx.type_of(field_def.did).instantiate(tcx, adt_args), ) } None => { @@ -3030,7 +2983,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) } hir::TyKind::Array(ty, length) => { - let length = self.lower_const_arg(length, FeedConstTy::WithTy(tcx.types.usize)); + let length = self.lower_const_arg(length, tcx.types.usize); Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length) } hir::TyKind::Infer(()) => { @@ -3070,8 +3023,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Keep this list of types in sync with the list of types that // the `RangePattern` trait is implemented for. ty::Int(_) | ty::Uint(_) | ty::Char => { - let start = self.lower_const_arg(start, FeedConstTy::WithTy(ty)); - let end = self.lower_const_arg(end, FeedConstTy::WithTy(ty)); + let start = self.lower_const_arg(start, ty); + let end = self.lower_const_arg(end, ty); Ok(ty::PatternKind::Range { start, end }) } _ => Err(self diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 7296ba6f964a4..a51355adf72fe 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -101,7 +101,7 @@ use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; pub use crate::collect::suggest_impl_trait; -use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer}; +use crate::hir_ty_lowering::HirTyLowerer; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } @@ -301,8 +301,8 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { pub fn lower_const_arg_for_rustdoc<'tcx>( tcx: TyCtxt<'tcx>, hir_ct: &hir::ConstArg<'tcx>, - feed: FeedConstTy<'tcx>, + ty: Ty<'tcx>, ) -> Const<'tcx> { let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id); - collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed) + collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, ty) } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d7366887d85c9..9f3ff0b2d03c2 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -21,7 +21,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, HirId, QPath, find_attr, is_range_literal}; use rustc_hir_analysis::NoVariantNamed; -use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _}; +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}; @@ -1749,10 +1749,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let count_span = count.span; let count = self.try_structurally_resolve_const( count_span, - self.normalize( - count_span, - self.lower_const_arg(count, FeedConstTy::WithTy(tcx.types.usize)), - ), + self.normalize(count_span, self.lower_const_arg(count, tcx.types.usize)), ); if let Some(count) = count.try_to_target_usize(tcx) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index a66ff2a23c250..91f91d9114449 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -14,8 +14,8 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{ check_generic_arg_count_for_call, lower_generic_args, }; use rustc_hir_analysis::hir_ty_lowering::{ - ExplicitLateBound, FeedConstTy, GenericArgCountMismatch, GenericArgCountResult, - GenericArgsLowerer, GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason, + ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgsLowerer, + GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason, }; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::{DefineOpaqueTypes, InferResult}; @@ -525,9 +525,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn lower_const_arg( &self, const_arg: &'tcx hir::ConstArg<'tcx>, - feed: FeedConstTy<'tcx>, + ty: Ty<'tcx>, ) -> ty::Const<'tcx> { - let ct = self.lowerer().lower_const_arg(const_arg, feed); + let ct = self.lowerer().lower_const_arg(const_arg, ty); self.register_wf_obligation( ct.into(), self.tcx.hir_span(const_arg.hir_id), @@ -1228,7 +1228,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Ambiguous parts of `ConstArg` are handled in the match arms below .lower_const_arg( ct.as_unambig_ct(), - FeedConstTy::with_type_of(self.fcx.tcx, param.def_id, preceding_args), + self.fcx + .tcx + .type_of(param.def_id) + .instantiate(self.fcx.tcx, preceding_args), ) .into(), (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index aab4e39855557..270f011b2b15f 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -7,7 +7,7 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{ check_generic_arg_count_for_call, lower_generic_args, }; use rustc_hir_analysis::hir_ty_lowering::{ - FeedConstTy, GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason, + GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason, }; use rustc_infer::infer::{ BoundRegionConversionTime, DefineOpaqueTypes, InferOk, RegionVariableOrigin, @@ -447,7 +447,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // We handle the ambig portions of `ConstArg` in the match arms below .lower_const_arg( ct.as_unambig_ct(), - FeedConstTy::with_type_of(self.cfcx.tcx, param.def_id, preceding_args), + self.cfcx + .tcx + .type_of(param.def_id) + .instantiate(self.cfcx.tcx, preceding_args), ) .into(), (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c93778ec8f0af..aa31cb1eae12f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -43,7 +43,6 @@ 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::{LangItem, PredicateOrigin, find_attr}; -use rustc_hir_analysis::hir_ty_lowering::FeedConstTy; use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty}; use rustc_middle::metadata::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; @@ -485,7 +484,7 @@ fn clean_hir_term<'tcx>( Ty::new_error_with_message(cx.tcx, span, "cannot find the associated constant") }; - let ct = lower_const_arg_for_rustdoc(cx.tcx, c, FeedConstTy::WithTy(ty)); + let ct = lower_const_arg_for_rustdoc(cx.tcx, c, ty); Term::Constant(clean_middle_const(ty::Binder::dummy(ct), cx)) } } @@ -663,12 +662,7 @@ fn clean_generic_param<'tcx>( ty: Box::new(clean_ty(ty, cx)), default: default.map(|ct| { Box::new( - lower_const_arg_for_rustdoc( - cx.tcx, - ct, - FeedConstTy::WithTy(lower_ty(cx.tcx, ty)), - ) - .to_string(), + lower_const_arg_for_rustdoc(cx.tcx, ct, lower_ty(cx.tcx, ty)).to_string(), ) }), }, @@ -1831,11 +1825,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T let length = match const_arg.kind { hir::ConstArgKind::Infer(..) | hir::ConstArgKind::Error(..) => "_".to_string(), hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) => { - let ct = lower_const_arg_for_rustdoc( - cx.tcx, - const_arg, - FeedConstTy::WithTy(cx.tcx.types.usize), - ); + let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, cx.tcx.types.usize); let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id); let ct = cx.tcx.normalize_erasing_regions(typing_env, ct); print_const(cx, ct) @@ -1846,11 +1836,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T | hir::ConstArgKind::Tup(..) | hir::ConstArgKind::Array(..) | hir::ConstArgKind::Literal(..) => { - let ct = lower_const_arg_for_rustdoc( - cx.tcx, - const_arg, - FeedConstTy::WithTy(cx.tcx.types.usize), - ); + let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, cx.tcx.types.usize); print_const(cx, ct) } }; From bf423e70f897120c574a6bcbcc061fe99a4138b8 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Sun, 11 Jan 2026 21:02:00 +0800 Subject: [PATCH 12/27] Bless tests --- .../associated-const-bindings/ambiguity.stderr | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr b/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr index a14afe9d6923b..806708f18d654 100644 --- a/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr +++ b/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr @@ -27,6 +27,12 @@ LL | const C: &'static str; ... LL | fn take1(_: impl Trait1) {} | ^^^^^^^ ambiguous associated constant `C` + | + = help: consider introducing a new type parameter `T` and adding `where` constraints: + where + T: Trait1, + T: Parent2::C = "?", + T: Parent1::C = "?" error: aborting due to 2 previous errors From d95613a3771f96a45046f7d36ad5d656f54cca3e Mon Sep 17 00:00:00 2001 From: mu001999 Date: Mon, 12 Jan 2026 23:50:32 +0800 Subject: [PATCH 13/27] Fix review comments --- .../rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 2 ++ src/librustdoc/clean/mod.rs | 14 +++----------- 2 files changed, 5 insertions(+), 11 deletions(-) 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 3dcc0232b301e..65d2d61e6fc45 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1283,6 +1283,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) }); + // FIXME(mgca): code duplication with other places we lower + // the rhs' of associated const bindings let ty = projection_term.map_bound(|alias| { tcx.type_of(alias.def_id).instantiate(tcx, alias.args) }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index aa31cb1eae12f..b42ee3c0fb329 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -471,19 +471,13 @@ fn clean_middle_term<'tcx>( fn clean_hir_term<'tcx>( assoc_item: Option, term: &hir::Term<'tcx>, - span: rustc_span::Span, cx: &mut DocContext<'tcx>, ) -> Term { match term { hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)), hir::Term::Const(c) => { - let ty = if let Some(assoc_item) = assoc_item { - // FIXME(generic_const_items): this should instantiate with the alias item's args - cx.tcx.type_of(assoc_item).instantiate_identity() - } else { - Ty::new_error_with_message(cx.tcx, span, "cannot find the associated constant") - }; - + // FIXME(generic_const_items): this should instantiate with the alias item's args + let ty = cx.tcx.type_of(assoc_item.unwrap()).instantiate_identity(); let ct = lower_const_arg_for_rustdoc(cx.tcx, c, ty); Term::Constant(clean_middle_const(ty::Binder::dummy(ct), cx)) } @@ -3168,9 +3162,7 @@ fn clean_assoc_item_constraint<'tcx>( .associated_items(trait_did) .find_by_ident_and_kind(cx.tcx, constraint.ident, assoc_tag, trait_did) .map(|item| item.def_id); - AssocItemConstraintKind::Equality { - term: clean_hir_term(assoc_item, term, constraint.span, cx), - } + AssocItemConstraintKind::Equality { term: clean_hir_term(assoc_item, term, cx) } } hir::AssocItemConstraintKind::Bound { bounds } => AssocItemConstraintKind::Bound { bounds: bounds.iter().filter_map(|b| clean_generic_bound(b, cx)).collect(), From 47089856ab3200d08f561714d87159660be8a2dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 13 Jan 2026 02:14:31 +0000 Subject: [PATCH 14/27] Update run-make test output --- .../missing-unstable-trait-bound/missing-bound.stderr | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr b/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr index 7196a1a6fed77..e8a7d808bbeef 100644 --- a/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr +++ b/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr @@ -1,9 +1,10 @@ -error[E0277]: the trait bound `T: Step` is not satisfied +error[E0277]: `std::ops::Range` is not an iterator --> missing-bound.rs:2:14 | 2 | for _ in t {} - | ^ the trait `Step` is not implemented for `T` + | ^ the nightly-only, unstable trait `Step` is not implemented for `T` | + = note: `Range` only implements `Iterator` for select types in the standard library, particularly integers; to see the full list of types, see the documentation for the unstable `Step` trait = note: required for `std::ops::Range` to implement `Iterator` = note: required for `std::ops::Range` to implement `IntoIterator` From 9b7f612d44057840d41bdae399d0b491820647a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 13 Jan 2026 02:57:40 +0000 Subject: [PATCH 15/27] Update main label --- library/core/src/iter/range.rs | 1 + .../run-make/missing-unstable-trait-bound/missing-bound.stderr | 2 +- tests/ui/range/range-1.stderr | 3 ++- tests/ui/trait-bounds/unstable-trait-suggestion.stderr | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 0be1e8699bf58..7880e18d7d318 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -23,6 +23,7 @@ unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u6 #[rustc_diagnostic_item = "range_step"] #[rustc_on_unimplemented( message = "`std::ops::Range<{Self}>` is not an iterator", + label = "not an iterator", note = "`Range` only implements `Iterator` for select types in the standard library, \ particularly integers; to see the full list of types, see the documentation for the \ unstable `Step` trait" diff --git a/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr b/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr index e8a7d808bbeef..d503751a2e933 100644 --- a/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr +++ b/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr @@ -2,7 +2,7 @@ error[E0277]: `std::ops::Range` is not an iterator --> missing-bound.rs:2:14 | 2 | for _ in t {} - | ^ the nightly-only, unstable trait `Step` is not implemented for `T` + | ^ not an iterator | = note: `Range` only implements `Iterator` for select types in the standard library, particularly integers; to see the full list of types, see the documentation for the unstable `Step` trait = note: required for `std::ops::Range` to implement `Iterator` diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr index 5491d06aee092..9682122539c56 100644 --- a/tests/ui/range/range-1.stderr +++ b/tests/ui/range/range-1.stderr @@ -8,8 +8,9 @@ error[E0277]: `std::ops::Range` is not an iterator --> $DIR/range-1.rs:9:14 | LL | for i in false..true {} - | ^^^^^^^^^^^ the nightly-only, unstable trait `Step` is not implemented for `bool` + | ^^^^^^^^^^^ not an iterator | + = help: the nightly-only, unstable trait `Step` is not implemented for `bool` = note: `Range` only implements `Iterator` for select types in the standard library, particularly integers; to see the full list of types, see the documentation for the unstable `Step` trait = note: required for `std::ops::Range` to implement `Iterator` = note: required for `std::ops::Range` to implement `IntoIterator` diff --git a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr index 011e56044bfec..5edaed0f4dfea 100644 --- a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr +++ b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr @@ -20,7 +20,7 @@ error[E0277]: `std::ops::Range` is not an iterator --> $DIR/unstable-trait-suggestion.rs:17:14 | LL | for _ in t {} - | ^ the nightly-only, unstable trait `Step` is not implemented for `T` + | ^ not an iterator | = note: `Range` only implements `Iterator` for select types in the standard library, particularly integers; to see the full list of types, see the documentation for the unstable `Step` trait = note: required for `std::ops::Range` to implement `Iterator` From e259373ce9eca5a10201d74a016a4a2e7ab42ed7 Mon Sep 17 00:00:00 2001 From: joboet Date: Tue, 6 Jan 2026 13:38:27 +0100 Subject: [PATCH 16/27] std: move `errno` and related functions into `sys::io` --- library/std/src/io/error.rs | 12 +- library/std/src/io/error/tests.rs | 3 +- library/std/src/sys/exit_guard.rs | 2 +- library/std/src/sys/fs/unix.rs | 4 +- library/std/src/sys/io/error/generic.rs | 15 ++ library/std/src/sys/io/error/hermit.rs | 35 ++++ library/std/src/sys/io/error/mod.rs | 55 ++++++ library/std/src/sys/io/error/motor.rs | 67 +++++++ library/std/src/sys/io/error/sgx.rs | 65 ++++++ library/std/src/sys/io/error/solid.rs | 19 ++ library/std/src/sys/io/error/teeos.rs | 64 ++++++ library/std/src/sys/io/error/uefi.rs | 104 ++++++++++ library/std/src/sys/io/error/unix.rs | 186 ++++++++++++++++++ library/std/src/sys/io/error/wasi.rs | 80 ++++++++ library/std/src/sys/io/error/windows.rs | 140 +++++++++++++ library/std/src/sys/io/error/xous.rs | 17 ++ library/std/src/sys/io/mod.rs | 20 +- .../std/src/sys/net/connection/socket/unix.rs | 2 +- library/std/src/sys/net/hostname/unix.rs | 2 +- library/std/src/sys/pal/hermit/mod.rs | 33 +--- library/std/src/sys/pal/hermit/os.rs | 8 - library/std/src/sys/pal/motor/mod.rs | 39 ---- library/std/src/sys/pal/motor/os.rs | 29 --- library/std/src/sys/pal/sgx/mod.rs | 50 ----- library/std/src/sys/pal/sgx/os.rs | 18 +- library/std/src/sys/pal/solid/mod.rs | 9 - library/std/src/sys/pal/solid/os.rs | 10 +- library/std/src/sys/pal/teeos/mod.rs | 55 ------ library/std/src/sys/pal/teeos/os.rs | 8 - library/std/src/sys/pal/uefi/mod.rs | 50 ----- library/std/src/sys/pal/uefi/os.rs | 53 ----- library/std/src/sys/pal/unix/futex.rs | 6 +- library/std/src/sys/pal/unix/mod.rs | 61 +----- library/std/src/sys/pal/unix/os.rs | 127 ------------ .../pal/unix/stack_overflow/thread_info.rs | 2 +- library/std/src/sys/pal/unsupported/common.rs | 8 - library/std/src/sys/pal/unsupported/os.rs | 8 - library/std/src/sys/pal/vexos/mod.rs | 4 +- library/std/src/sys/pal/vexos/os.rs | 4 +- library/std/src/sys/pal/wasi/helpers.rs | 56 +----- library/std/src/sys/pal/wasi/mod.rs | 2 +- library/std/src/sys/pal/wasi/os.rs | 30 +-- library/std/src/sys/pal/windows/mod.rs | 78 -------- library/std/src/sys/pal/windows/os.rs | 60 ------ library/std/src/sys/pal/xous/os.rs | 9 - library/std/src/sys/pal/zkvm/mod.rs | 8 - library/std/src/sys/pal/zkvm/os.rs | 8 - library/std/src/sys/process/uefi.rs | 2 +- library/std/src/sys/process/unix/common.rs | 2 +- library/std/src/sys/process/unix/unix.rs | 2 +- library/std/src/sys/random/linux.rs | 2 +- library/std/src/sys/sync/condvar/windows7.rs | 4 +- library/std/src/sys/thread/unix.rs | 9 +- 53 files changed, 900 insertions(+), 846 deletions(-) create mode 100644 library/std/src/sys/io/error/generic.rs create mode 100644 library/std/src/sys/io/error/hermit.rs create mode 100644 library/std/src/sys/io/error/mod.rs create mode 100644 library/std/src/sys/io/error/motor.rs create mode 100644 library/std/src/sys/io/error/sgx.rs create mode 100644 library/std/src/sys/io/error/solid.rs create mode 100644 library/std/src/sys/io/error/teeos.rs create mode 100644 library/std/src/sys/io/error/uefi.rs create mode 100644 library/std/src/sys/io/error/unix.rs create mode 100644 library/std/src/sys/io/error/wasi.rs create mode 100644 library/std/src/sys/io/error/windows.rs create mode 100644 library/std/src/sys/io/error/xous.rs diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 528eb185df088..b19087e7424a0 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -653,7 +653,7 @@ impl Error { #[must_use] #[inline] pub fn last_os_error() -> Error { - Error::from_raw_os_error(sys::os::errno()) + Error::from_raw_os_error(sys::io::errno()) } /// Creates a new instance of an [`Error`] from a particular OS error code. @@ -1004,7 +1004,7 @@ impl Error { #[inline] pub fn kind(&self) -> ErrorKind { match self.repr.data() { - ErrorData::Os(code) => sys::decode_error_kind(code), + ErrorData::Os(code) => sys::io::decode_error_kind(code), ErrorData::Custom(c) => c.kind, ErrorData::Simple(kind) => kind, ErrorData::SimpleMessage(m) => m.kind, @@ -1014,7 +1014,7 @@ impl Error { #[inline] pub(crate) fn is_interrupted(&self) -> bool { match self.repr.data() { - ErrorData::Os(code) => sys::is_interrupted(code), + ErrorData::Os(code) => sys::io::is_interrupted(code), ErrorData::Custom(c) => c.kind == ErrorKind::Interrupted, ErrorData::Simple(kind) => kind == ErrorKind::Interrupted, ErrorData::SimpleMessage(m) => m.kind == ErrorKind::Interrupted, @@ -1028,8 +1028,8 @@ impl fmt::Debug for Repr { ErrorData::Os(code) => fmt .debug_struct("Os") .field("code", &code) - .field("kind", &sys::decode_error_kind(code)) - .field("message", &sys::os::error_string(code)) + .field("kind", &sys::io::decode_error_kind(code)) + .field("message", &sys::io::error_string(code)) .finish(), ErrorData::Custom(c) => fmt::Debug::fmt(&c, fmt), ErrorData::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(), @@ -1047,7 +1047,7 @@ impl fmt::Display for Error { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self.repr.data() { ErrorData::Os(code) => { - let detail = sys::os::error_string(code); + let detail = sys::io::error_string(code); write!(fmt, "{detail} (os error {code})") } ErrorData::Custom(ref c) => c.error.fmt(fmt), diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs index 3e4029768eb85..eef44c6ac3b6a 100644 --- a/library/std/src/io/error/tests.rs +++ b/library/std/src/io/error/tests.rs @@ -1,7 +1,6 @@ use super::{Custom, Error, ErrorData, ErrorKind, Repr, SimpleMessage, const_error}; use crate::assert_matches::assert_matches; -use crate::sys::decode_error_kind; -use crate::sys::os::error_string; +use crate::sys::io::{decode_error_kind, error_string}; use crate::{error, fmt}; #[test] diff --git a/library/std/src/sys/exit_guard.rs b/library/std/src/sys/exit_guard.rs index 00b91842e9dba..e7d7a478a5baa 100644 --- a/library/std/src/sys/exit_guard.rs +++ b/library/std/src/sys/exit_guard.rs @@ -34,7 +34,7 @@ cfg_select! { // lifetime of the thread. Additionally, accesses to `errno` are // async-signal-safe, so this function is available in all imaginable // circumstances. - let this_thread_id = crate::sys::os::errno_location(); + let this_thread_id = crate::sys::io::errno_location(); match EXITING_THREAD_ID.compare_exchange(ptr::null_mut(), this_thread_id, Acquire, Relaxed) { Ok(_) => { // This is the first thread to call `unique_thread_exit`, diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 1cc2edd0cf474..716ca9783d1fb 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -726,7 +726,7 @@ impl Iterator for ReadDir { target_os = "wasi", ))] fn next(&mut self) -> Option> { - use crate::sys::os::{errno, set_errno}; + use crate::sys::io::{errno, set_errno}; if self.end_of_stream { return None; @@ -864,7 +864,7 @@ impl Iterator for ReadDir { /// The downside is that it costs an extra syscall, so we only do it for debug. #[inline] pub(crate) fn debug_assert_fd_is_open(fd: RawFd) { - use crate::sys::os::errno; + use crate::sys::io::errno; // this is similar to assert_unsafe_precondition!() but it doesn't require const if core::ub_checks::check_library_ub() { diff --git a/library/std/src/sys/io/error/generic.rs b/library/std/src/sys/io/error/generic.rs new file mode 100644 index 0000000000000..fc70fbaba7e8c --- /dev/null +++ b/library/std/src/sys/io/error/generic.rs @@ -0,0 +1,15 @@ +pub fn errno() -> i32 { + 0 +} + +pub fn is_interrupted(_code: i32) -> bool { + false +} + +pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { + crate::io::ErrorKind::Uncategorized +} + +pub fn error_string(_errno: i32) -> String { + "operation successful".to_string() +} diff --git a/library/std/src/sys/io/error/hermit.rs b/library/std/src/sys/io/error/hermit.rs new file mode 100644 index 0000000000000..5f42144bb7cfb --- /dev/null +++ b/library/std/src/sys/io/error/hermit.rs @@ -0,0 +1,35 @@ +use crate::io; + +pub fn errno() -> i32 { + unsafe { hermit_abi::get_errno() } +} + +#[inline] +pub fn is_interrupted(errno: i32) -> bool { + errno == hermit_abi::errno::EINTR +} + +pub fn decode_error_kind(errno: i32) -> io::ErrorKind { + match errno { + hermit_abi::errno::EACCES => io::ErrorKind::PermissionDenied, + hermit_abi::errno::EADDRINUSE => io::ErrorKind::AddrInUse, + hermit_abi::errno::EADDRNOTAVAIL => io::ErrorKind::AddrNotAvailable, + hermit_abi::errno::EAGAIN => io::ErrorKind::WouldBlock, + hermit_abi::errno::ECONNABORTED => io::ErrorKind::ConnectionAborted, + hermit_abi::errno::ECONNREFUSED => io::ErrorKind::ConnectionRefused, + hermit_abi::errno::ECONNRESET => io::ErrorKind::ConnectionReset, + hermit_abi::errno::EEXIST => io::ErrorKind::AlreadyExists, + hermit_abi::errno::EINTR => io::ErrorKind::Interrupted, + hermit_abi::errno::EINVAL => io::ErrorKind::InvalidInput, + hermit_abi::errno::ENOENT => io::ErrorKind::NotFound, + hermit_abi::errno::ENOTCONN => io::ErrorKind::NotConnected, + hermit_abi::errno::EPERM => io::ErrorKind::PermissionDenied, + hermit_abi::errno::EPIPE => io::ErrorKind::BrokenPipe, + hermit_abi::errno::ETIMEDOUT => io::ErrorKind::TimedOut, + _ => io::ErrorKind::Uncategorized, + } +} + +pub fn error_string(errno: i32) -> String { + hermit_abi::error_string(errno).to_string() +} diff --git a/library/std/src/sys/io/error/mod.rs b/library/std/src/sys/io/error/mod.rs new file mode 100644 index 0000000000000..d7a0b9b4b301d --- /dev/null +++ b/library/std/src/sys/io/error/mod.rs @@ -0,0 +1,55 @@ +cfg_select! { + target_os = "hermit" => { + mod hermit; + pub use hermit::*; + } + target_os = "motor" => { + mod motor; + pub use motor::*; + } + all(target_vendor = "fortanix", target_env = "sgx") => { + mod sgx; + pub use sgx::*; + } + target_os = "solid_asp3" => { + mod solid; + pub use solid::*; + } + target_os = "teeos" => { + mod teeos; + pub use teeos::*; + } + target_os = "uefi" => { + mod uefi; + pub use uefi::*; + } + target_family = "unix" => { + mod unix; + pub use unix::*; + } + target_os = "wasi" => { + mod wasi; + pub use wasi::*; + } + target_os = "windows" => { + mod windows; + pub use windows::*; + } + target_os = "xous" => { + mod xous; + pub use xous::*; + } + any( + target_os = "vexos", + target_family = "wasm", + target_os = "zkvm", + ) => { + mod generic; + pub use generic::*; + } +} + +pub type RawOsError = cfg_select! { + target_os = "uefi" => usize, + _ => i32, +}; diff --git a/library/std/src/sys/io/error/motor.rs b/library/std/src/sys/io/error/motor.rs new file mode 100644 index 0000000000000..7d612d817cdd7 --- /dev/null +++ b/library/std/src/sys/io/error/motor.rs @@ -0,0 +1,67 @@ +use crate::io; +use crate::sys::io::RawOsError; + +pub fn errno() -> RawOsError { + // Not used in Motor OS because it is ambiguous: Motor OS + // is micro-kernel-based, and I/O happens via a shared-memory + // ring buffer, so an I/O operation that on a unix is a syscall + // may involve no sycalls on Motor OS at all, or a syscall + // that e.g. waits for a notification from the I/O driver + // (sys-io); and the wait syscall may succeed, but the + // driver may report an I/O error; or a bunch of results + // for several I/O operations, some successful and some + // not. + // + // Also I/O operations in a Motor OS process are handled by a + // separate runtime background/I/O thread, so it is really hard + // to define what "last system error in the current thread" + // actually means. + let error_code: moto_rt::ErrorCode = moto_rt::Error::Unknown.into(); + error_code.into() +} + +pub fn is_interrupted(_code: io::RawOsError) -> bool { + false // Motor OS doesn't have signals. +} + +pub fn decode_error_kind(code: io::RawOsError) -> io::ErrorKind { + if code < 0 || code > u16::MAX.into() { + return io::ErrorKind::Uncategorized; + } + + let error = moto_rt::Error::from(code as moto_rt::ErrorCode); + + match error { + moto_rt::Error::Unspecified => io::ErrorKind::Uncategorized, + moto_rt::Error::Unknown => io::ErrorKind::Uncategorized, + moto_rt::Error::NotReady => io::ErrorKind::WouldBlock, + moto_rt::Error::NotImplemented => io::ErrorKind::Unsupported, + moto_rt::Error::VersionTooHigh => io::ErrorKind::Unsupported, + moto_rt::Error::VersionTooLow => io::ErrorKind::Unsupported, + moto_rt::Error::InvalidArgument => io::ErrorKind::InvalidInput, + moto_rt::Error::OutOfMemory => io::ErrorKind::OutOfMemory, + moto_rt::Error::NotAllowed => io::ErrorKind::PermissionDenied, + moto_rt::Error::NotFound => io::ErrorKind::NotFound, + moto_rt::Error::InternalError => io::ErrorKind::Other, + moto_rt::Error::TimedOut => io::ErrorKind::TimedOut, + moto_rt::Error::AlreadyInUse => io::ErrorKind::AlreadyExists, + moto_rt::Error::UnexpectedEof => io::ErrorKind::UnexpectedEof, + moto_rt::Error::InvalidFilename => io::ErrorKind::InvalidFilename, + moto_rt::Error::NotADirectory => io::ErrorKind::NotADirectory, + moto_rt::Error::BadHandle => io::ErrorKind::InvalidInput, + moto_rt::Error::FileTooLarge => io::ErrorKind::FileTooLarge, + moto_rt::Error::NotConnected => io::ErrorKind::NotConnected, + moto_rt::Error::StorageFull => io::ErrorKind::StorageFull, + moto_rt::Error::InvalidData => io::ErrorKind::InvalidData, + _ => io::ErrorKind::Uncategorized, + } +} + +pub fn error_string(errno: RawOsError) -> String { + let error: moto_rt::Error = match errno { + x if x < 0 => moto_rt::Error::Unknown, + x if x > u16::MAX.into() => moto_rt::Error::Unknown, + x => (x as moto_rt::ErrorCode).into(), /* u16 */ + }; + format!("{}", error) +} diff --git a/library/std/src/sys/io/error/sgx.rs b/library/std/src/sys/io/error/sgx.rs new file mode 100644 index 0000000000000..8b3e08b0b661b --- /dev/null +++ b/library/std/src/sys/io/error/sgx.rs @@ -0,0 +1,65 @@ +use fortanix_sgx_abi::{Error, RESULT_SUCCESS}; + +use crate::io; + +pub fn errno() -> i32 { + RESULT_SUCCESS +} + +#[inline] +pub fn is_interrupted(code: i32) -> bool { + code == fortanix_sgx_abi::Error::Interrupted as _ +} + +pub fn decode_error_kind(code: i32) -> io::ErrorKind { + // FIXME: not sure how to make sure all variants of Error are covered + if code == Error::NotFound as _ { + io::ErrorKind::NotFound + } else if code == Error::PermissionDenied as _ { + io::ErrorKind::PermissionDenied + } else if code == Error::ConnectionRefused as _ { + io::ErrorKind::ConnectionRefused + } else if code == Error::ConnectionReset as _ { + io::ErrorKind::ConnectionReset + } else if code == Error::ConnectionAborted as _ { + io::ErrorKind::ConnectionAborted + } else if code == Error::NotConnected as _ { + io::ErrorKind::NotConnected + } else if code == Error::AddrInUse as _ { + io::ErrorKind::AddrInUse + } else if code == Error::AddrNotAvailable as _ { + io::ErrorKind::AddrNotAvailable + } else if code == Error::BrokenPipe as _ { + io::ErrorKind::BrokenPipe + } else if code == Error::AlreadyExists as _ { + io::ErrorKind::AlreadyExists + } else if code == Error::WouldBlock as _ { + io::ErrorKind::WouldBlock + } else if code == Error::InvalidInput as _ { + io::ErrorKind::InvalidInput + } else if code == Error::InvalidData as _ { + io::ErrorKind::InvalidData + } else if code == Error::TimedOut as _ { + io::ErrorKind::TimedOut + } else if code == Error::WriteZero as _ { + io::ErrorKind::WriteZero + } else if code == Error::Interrupted as _ { + io::ErrorKind::Interrupted + } else if code == Error::Other as _ { + io::ErrorKind::Uncategorized + } else if code == Error::UnexpectedEof as _ { + io::ErrorKind::UnexpectedEof + } else { + io::ErrorKind::Uncategorized + } +} + +pub fn error_string(errno: i32) -> String { + if errno == RESULT_SUCCESS { + "operation successful".into() + } else if ((Error::UserRangeStart as _)..=(Error::UserRangeEnd as _)).contains(&errno) { + format!("user-specified error {errno:08x}") + } else { + decode_error_kind(errno).as_str().into() + } +} diff --git a/library/std/src/sys/io/error/solid.rs b/library/std/src/sys/io/error/solid.rs new file mode 100644 index 0000000000000..8e9503272abbc --- /dev/null +++ b/library/std/src/sys/io/error/solid.rs @@ -0,0 +1,19 @@ +use crate::io; +use crate::sys::pal::error; + +pub fn errno() -> i32 { + 0 +} + +#[inline] +pub fn is_interrupted(code: i32) -> bool { + crate::sys::net::is_interrupted(code) +} + +pub fn decode_error_kind(code: i32) -> io::ErrorKind { + error::decode_error_kind(code) +} + +pub fn error_string(errno: i32) -> String { + if let Some(name) = error::error_name(errno) { name.to_owned() } else { format!("{errno}") } +} diff --git a/library/std/src/sys/io/error/teeos.rs b/library/std/src/sys/io/error/teeos.rs new file mode 100644 index 0000000000000..18826ffc3894f --- /dev/null +++ b/library/std/src/sys/io/error/teeos.rs @@ -0,0 +1,64 @@ +use crate::io; + +pub fn errno() -> i32 { + unsafe { (*libc::__errno_location()) as i32 } +} + +#[inline] +pub fn is_interrupted(errno: i32) -> bool { + errno == libc::EINTR +} + +// Note: code below is 1:1 copied from unix/mod.rs +pub fn decode_error_kind(errno: i32) -> io::ErrorKind { + use io::ErrorKind::*; + match errno as libc::c_int { + libc::E2BIG => ArgumentListTooLong, + libc::EADDRINUSE => AddrInUse, + libc::EADDRNOTAVAIL => AddrNotAvailable, + libc::EBUSY => ResourceBusy, + libc::ECONNABORTED => ConnectionAborted, + libc::ECONNREFUSED => ConnectionRefused, + libc::ECONNRESET => ConnectionReset, + libc::EDEADLK => Deadlock, + libc::EDQUOT => QuotaExceeded, + libc::EEXIST => AlreadyExists, + libc::EFBIG => FileTooLarge, + libc::EHOSTUNREACH => HostUnreachable, + libc::EINTR => Interrupted, + libc::EINVAL => InvalidInput, + libc::EISDIR => IsADirectory, + libc::ELOOP => FilesystemLoop, + libc::ENOENT => NotFound, + libc::ENOMEM => OutOfMemory, + libc::ENOSPC => StorageFull, + libc::ENOSYS => Unsupported, + libc::EMLINK => TooManyLinks, + libc::ENAMETOOLONG => InvalidFilename, + libc::ENETDOWN => NetworkDown, + libc::ENETUNREACH => NetworkUnreachable, + libc::ENOTCONN => NotConnected, + libc::ENOTDIR => NotADirectory, + libc::ENOTEMPTY => DirectoryNotEmpty, + libc::EPIPE => BrokenPipe, + libc::EROFS => ReadOnlyFilesystem, + libc::ESPIPE => NotSeekable, + libc::ESTALE => StaleNetworkFileHandle, + libc::ETIMEDOUT => TimedOut, + libc::ETXTBSY => ExecutableFileBusy, + libc::EXDEV => CrossesDevices, + + libc::EACCES | libc::EPERM => PermissionDenied, + + // These two constants can have the same value on some systems, + // but different values on others, so we can't use a match + // clause + x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock, + + _ => Uncategorized, + } +} + +pub fn error_string(_errno: i32) -> String { + "error string unimplemented".to_string() +} diff --git a/library/std/src/sys/io/error/uefi.rs b/library/std/src/sys/io/error/uefi.rs new file mode 100644 index 0000000000000..bedea240d523b --- /dev/null +++ b/library/std/src/sys/io/error/uefi.rs @@ -0,0 +1,104 @@ +use r_efi::efi::Status; + +use crate::io; + +pub fn errno() -> io::RawOsError { + 0 +} + +pub fn is_interrupted(_code: io::RawOsError) -> bool { + false +} + +pub fn decode_error_kind(code: io::RawOsError) -> io::ErrorKind { + match Status::from_usize(code) { + Status::ALREADY_STARTED + | Status::COMPROMISED_DATA + | Status::CONNECTION_FIN + | Status::CRC_ERROR + | Status::DEVICE_ERROR + | Status::END_OF_MEDIA + | Status::HTTP_ERROR + | Status::ICMP_ERROR + | Status::INCOMPATIBLE_VERSION + | Status::LOAD_ERROR + | Status::MEDIA_CHANGED + | Status::NO_MAPPING + | Status::NO_MEDIA + | Status::NOT_STARTED + | Status::PROTOCOL_ERROR + | Status::PROTOCOL_UNREACHABLE + | Status::TFTP_ERROR + | Status::VOLUME_CORRUPTED => io::ErrorKind::Other, + Status::BAD_BUFFER_SIZE | Status::INVALID_LANGUAGE => io::ErrorKind::InvalidData, + Status::ABORTED => io::ErrorKind::ConnectionAborted, + Status::ACCESS_DENIED => io::ErrorKind::PermissionDenied, + Status::BUFFER_TOO_SMALL => io::ErrorKind::FileTooLarge, + Status::CONNECTION_REFUSED => io::ErrorKind::ConnectionRefused, + Status::CONNECTION_RESET => io::ErrorKind::ConnectionReset, + Status::END_OF_FILE => io::ErrorKind::UnexpectedEof, + Status::HOST_UNREACHABLE => io::ErrorKind::HostUnreachable, + Status::INVALID_PARAMETER => io::ErrorKind::InvalidInput, + Status::IP_ADDRESS_CONFLICT => io::ErrorKind::AddrInUse, + Status::NETWORK_UNREACHABLE => io::ErrorKind::NetworkUnreachable, + Status::NO_RESPONSE => io::ErrorKind::HostUnreachable, + Status::NOT_FOUND => io::ErrorKind::NotFound, + Status::NOT_READY => io::ErrorKind::ResourceBusy, + Status::OUT_OF_RESOURCES => io::ErrorKind::OutOfMemory, + Status::SECURITY_VIOLATION => io::ErrorKind::PermissionDenied, + Status::TIMEOUT => io::ErrorKind::TimedOut, + Status::UNSUPPORTED => io::ErrorKind::Unsupported, + Status::VOLUME_FULL => io::ErrorKind::StorageFull, + Status::WRITE_PROTECTED => io::ErrorKind::ReadOnlyFilesystem, + _ => io::ErrorKind::Uncategorized, + } +} + +pub fn error_string(errno: io::RawOsError) -> String { + // Keep the List in Alphabetical Order + // The Messages are taken from UEFI Specification Appendix D - Status Codes + #[rustfmt::skip] + let msg = match Status::from_usize(errno) { + Status::ABORTED => "The operation was aborted.", + Status::ACCESS_DENIED => "Access was denied.", + Status::ALREADY_STARTED => "The protocol has already been started.", + Status::BAD_BUFFER_SIZE => "The buffer was not the proper size for the request.", + Status::BUFFER_TOO_SMALL => "The buffer is not large enough to hold the requested data. The required buffer size is returned in the appropriate parameter when this error occurs.", + Status::COMPROMISED_DATA => "The security status of the data is unknown or compromised and the data must be updated or replaced to restore a valid security status.", + Status::CONNECTION_FIN => "The receiving operation fails because the communication peer has closed the connection and there is no more data in the receive buffer of the instance.", + Status::CONNECTION_REFUSED => "The receiving or transmission operation fails because this connection is refused.", + Status::CONNECTION_RESET => "The connect fails because the connection is reset either by instance itself or the communication peer.", + Status::CRC_ERROR => "A CRC error was detected.", + Status::DEVICE_ERROR => "The physical device reported an error while attempting the operation.", + Status::END_OF_FILE => "The end of the file was reached.", + Status::END_OF_MEDIA => "Beginning or end of media was reached", + Status::HOST_UNREACHABLE => "The remote host is not reachable.", + Status::HTTP_ERROR => "A HTTP error occurred during the network operation.", + Status::ICMP_ERROR => "An ICMP error occurred during the network operation.", + Status::INCOMPATIBLE_VERSION => "The function encountered an internal version that was incompatible with a version requested by the caller.", + Status::INVALID_LANGUAGE => "The language specified was invalid.", + Status::INVALID_PARAMETER => "A parameter was incorrect.", + Status::IP_ADDRESS_CONFLICT => "There is an address conflict address allocation", + Status::LOAD_ERROR => "The image failed to load.", + Status::MEDIA_CHANGED => "The medium in the device has changed since the last access.", + Status::NETWORK_UNREACHABLE => "The network containing the remote host is not reachable.", + Status::NO_MAPPING => "A mapping to a device does not exist.", + Status::NO_MEDIA => "The device does not contain any medium to perform the operation.", + Status::NO_RESPONSE => "The server was not found or did not respond to the request.", + Status::NOT_FOUND => "The item was not found.", + Status::NOT_READY => "There is no data pending upon return.", + Status::NOT_STARTED => "The protocol has not been started.", + Status::OUT_OF_RESOURCES => "A resource has run out.", + Status::PROTOCOL_ERROR => "A protocol error occurred during the network operation.", + Status::PROTOCOL_UNREACHABLE => "An ICMP protocol unreachable error is received.", + Status::SECURITY_VIOLATION => "The function was not performed due to a security violation.", + Status::TFTP_ERROR => "A TFTP error occurred during the network operation.", + Status::TIMEOUT => "The timeout time expired.", + Status::UNSUPPORTED => "The operation is not supported.", + Status::VOLUME_FULL => "There is no more space on the file system.", + Status::VOLUME_CORRUPTED => "An inconstancy was detected on the file system causing the operating to fail.", + Status::WRITE_PROTECTED => "The device cannot be written to.", + _ => return format!("Status: {errno}"), + }; + msg.to_owned() +} diff --git a/library/std/src/sys/io/error/unix.rs b/library/std/src/sys/io/error/unix.rs new file mode 100644 index 0000000000000..b10343b2752c2 --- /dev/null +++ b/library/std/src/sys/io/error/unix.rs @@ -0,0 +1,186 @@ +use crate::ffi::{CStr, c_char, c_int}; +use crate::io; + +unsafe extern "C" { + #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] + #[cfg_attr( + any( + target_os = "linux", + target_os = "emscripten", + target_os = "fuchsia", + target_os = "l4re", + target_os = "hurd", + ), + link_name = "__errno_location" + )] + #[cfg_attr( + any( + target_os = "netbsd", + target_os = "openbsd", + target_os = "cygwin", + target_os = "android", + target_os = "redox", + target_os = "nuttx", + target_env = "newlib" + ), + link_name = "__errno" + )] + #[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")] + #[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")] + #[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")] + #[cfg_attr(target_os = "haiku", link_name = "_errnop")] + #[cfg_attr(target_os = "aix", link_name = "_Errno")] + // SAFETY: this will always return the same pointer on a given thread. + #[unsafe(ffi_const)] + pub safe fn errno_location() -> *mut c_int; +} + +/// Returns the platform-specific value of errno +#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] +#[inline] +pub fn errno() -> i32 { + unsafe { (*errno_location()) as i32 } +} + +/// Sets the platform-specific value of errno +// needed for readdir and syscall! +#[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks"), not(target_os = "rtems")))] +#[allow(dead_code)] // but not all target cfgs actually end up using it +#[inline] +pub fn set_errno(e: i32) { + unsafe { *errno_location() = e as c_int } +} + +#[cfg(target_os = "vxworks")] +#[inline] +pub fn errno() -> i32 { + unsafe { libc::errnoGet() } +} + +#[cfg(target_os = "rtems")] +#[inline] +pub fn errno() -> i32 { + unsafe extern "C" { + #[thread_local] + static _tls_errno: c_int; + } + + unsafe { _tls_errno as i32 } +} + +#[cfg(target_os = "dragonfly")] +#[inline] +pub fn errno() -> i32 { + unsafe extern "C" { + #[thread_local] + static errno: c_int; + } + + unsafe { errno as i32 } +} + +#[cfg(target_os = "dragonfly")] +#[allow(dead_code)] +#[inline] +pub fn set_errno(e: i32) { + unsafe extern "C" { + #[thread_local] + static mut errno: c_int; + } + + unsafe { + errno = e; + } +} + +#[inline] +pub fn is_interrupted(errno: i32) -> bool { + errno == libc::EINTR +} + +pub fn decode_error_kind(errno: i32) -> io::ErrorKind { + use io::ErrorKind::*; + match errno as libc::c_int { + libc::E2BIG => ArgumentListTooLong, + libc::EADDRINUSE => AddrInUse, + libc::EADDRNOTAVAIL => AddrNotAvailable, + libc::EBUSY => ResourceBusy, + libc::ECONNABORTED => ConnectionAborted, + libc::ECONNREFUSED => ConnectionRefused, + libc::ECONNRESET => ConnectionReset, + libc::EDEADLK => Deadlock, + libc::EDQUOT => QuotaExceeded, + libc::EEXIST => AlreadyExists, + libc::EFBIG => FileTooLarge, + libc::EHOSTUNREACH => HostUnreachable, + libc::EINTR => Interrupted, + libc::EINVAL => InvalidInput, + libc::EISDIR => IsADirectory, + libc::ELOOP => FilesystemLoop, + libc::ENOENT => NotFound, + libc::ENOMEM => OutOfMemory, + libc::ENOSPC => StorageFull, + libc::ENOSYS => Unsupported, + libc::EMLINK => TooManyLinks, + libc::ENAMETOOLONG => InvalidFilename, + libc::ENETDOWN => NetworkDown, + libc::ENETUNREACH => NetworkUnreachable, + libc::ENOTCONN => NotConnected, + libc::ENOTDIR => NotADirectory, + #[cfg(not(target_os = "aix"))] + libc::ENOTEMPTY => DirectoryNotEmpty, + libc::EPIPE => BrokenPipe, + libc::EROFS => ReadOnlyFilesystem, + libc::ESPIPE => NotSeekable, + libc::ESTALE => StaleNetworkFileHandle, + libc::ETIMEDOUT => TimedOut, + libc::ETXTBSY => ExecutableFileBusy, + libc::EXDEV => CrossesDevices, + libc::EINPROGRESS => InProgress, + libc::EOPNOTSUPP => Unsupported, + + libc::EACCES | libc::EPERM => PermissionDenied, + + // These two constants can have the same value on some systems, + // but different values on others, so we can't use a match + // clause + x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock, + + _ => Uncategorized, + } +} + +/// Gets a detailed string description for the given error number. +pub fn error_string(errno: i32) -> String { + const TMPBUF_SZ: usize = 128; + + unsafe extern "C" { + #[cfg_attr( + all( + any( + target_os = "linux", + target_os = "hurd", + target_env = "newlib", + target_os = "cygwin" + ), + not(target_env = "ohos") + ), + link_name = "__xpg_strerror_r" + )] + fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) -> c_int; + } + + let mut buf = [0 as c_char; TMPBUF_SZ]; + + let p = buf.as_mut_ptr(); + unsafe { + if strerror_r(errno as c_int, p, buf.len()) < 0 { + panic!("strerror_r failure"); + } + + let p = p as *const _; + // We can't always expect a UTF-8 environment. When we don't get that luxury, + // it's better to give a low-quality error message than none at all. + String::from_utf8_lossy(CStr::from_ptr(p).to_bytes()).into() + } +} diff --git a/library/std/src/sys/io/error/wasi.rs b/library/std/src/sys/io/error/wasi.rs new file mode 100644 index 0000000000000..719fc0c900adc --- /dev/null +++ b/library/std/src/sys/io/error/wasi.rs @@ -0,0 +1,80 @@ +use crate::ffi::CStr; +use crate::io as std_io; + +unsafe extern "C" { + #[thread_local] + #[link_name = "errno"] + static mut libc_errno: libc::c_int; +} + +pub fn errno() -> i32 { + unsafe { libc_errno as i32 } +} + +pub fn set_errno(val: i32) { + unsafe { + libc_errno = val; + } +} + +#[inline] +pub fn is_interrupted(errno: i32) -> bool { + errno == libc::EINTR +} + +pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { + use std_io::ErrorKind::*; + match errno as libc::c_int { + libc::E2BIG => ArgumentListTooLong, + libc::EADDRINUSE => AddrInUse, + libc::EADDRNOTAVAIL => AddrNotAvailable, + libc::EBUSY => ResourceBusy, + libc::ECONNABORTED => ConnectionAborted, + libc::ECONNREFUSED => ConnectionRefused, + libc::ECONNRESET => ConnectionReset, + libc::EDEADLK => Deadlock, + libc::EDQUOT => QuotaExceeded, + libc::EEXIST => AlreadyExists, + libc::EFBIG => FileTooLarge, + libc::EHOSTUNREACH => HostUnreachable, + libc::EINTR => Interrupted, + libc::EINVAL => InvalidInput, + libc::EISDIR => IsADirectory, + libc::ELOOP => FilesystemLoop, + libc::ENOENT => NotFound, + libc::ENOMEM => OutOfMemory, + libc::ENOSPC => StorageFull, + libc::ENOSYS => Unsupported, + libc::EMLINK => TooManyLinks, + libc::ENAMETOOLONG => InvalidFilename, + libc::ENETDOWN => NetworkDown, + libc::ENETUNREACH => NetworkUnreachable, + libc::ENOTCONN => NotConnected, + libc::ENOTDIR => NotADirectory, + libc::EPIPE => BrokenPipe, + libc::EROFS => ReadOnlyFilesystem, + libc::ESPIPE => NotSeekable, + libc::ESTALE => StaleNetworkFileHandle, + libc::ETIMEDOUT => TimedOut, + libc::ETXTBSY => ExecutableFileBusy, + libc::EXDEV => CrossesDevices, + libc::EINPROGRESS => InProgress, + libc::EOPNOTSUPP => Unsupported, + libc::EACCES | libc::EPERM => PermissionDenied, + libc::EWOULDBLOCK => WouldBlock, + + _ => Uncategorized, + } +} + +pub fn error_string(errno: i32) -> String { + let mut buf = [0 as libc::c_char; 1024]; + + let p = buf.as_mut_ptr(); + unsafe { + if libc::strerror_r(errno as libc::c_int, p, buf.len()) < 0 { + panic!("strerror_r failure"); + } + str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned() + } +} diff --git a/library/std/src/sys/io/error/windows.rs b/library/std/src/sys/io/error/windows.rs new file mode 100644 index 0000000000000..e02197ac67756 --- /dev/null +++ b/library/std/src/sys/io/error/windows.rs @@ -0,0 +1,140 @@ +use crate::sys::pal::{api, c}; +use crate::{io, ptr}; + +pub fn errno() -> i32 { + api::get_last_error().code as i32 +} + +#[inline] +pub fn is_interrupted(_errno: i32) -> bool { + false +} + +pub fn decode_error_kind(errno: i32) -> io::ErrorKind { + use io::ErrorKind::*; + + match errno as u32 { + c::ERROR_ACCESS_DENIED => return PermissionDenied, + c::ERROR_ALREADY_EXISTS => return AlreadyExists, + c::ERROR_FILE_EXISTS => return AlreadyExists, + c::ERROR_BROKEN_PIPE => return BrokenPipe, + c::ERROR_FILE_NOT_FOUND + | c::ERROR_PATH_NOT_FOUND + | c::ERROR_INVALID_DRIVE + | c::ERROR_BAD_NETPATH + | c::ERROR_BAD_NET_NAME => return NotFound, + c::ERROR_NO_DATA => return BrokenPipe, + c::ERROR_INVALID_NAME | c::ERROR_BAD_PATHNAME => return InvalidFilename, + c::ERROR_INVALID_PARAMETER => return InvalidInput, + c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return OutOfMemory, + c::ERROR_SEM_TIMEOUT + | c::WAIT_TIMEOUT + | c::ERROR_DRIVER_CANCEL_TIMEOUT + | c::ERROR_OPERATION_ABORTED + | c::ERROR_SERVICE_REQUEST_TIMEOUT + | c::ERROR_COUNTER_TIMEOUT + | c::ERROR_TIMEOUT + | c::ERROR_RESOURCE_CALL_TIMED_OUT + | c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT + | c::ERROR_CTX_CLIENT_QUERY_TIMEOUT + | c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT + | c::ERROR_DS_TIMELIMIT_EXCEEDED + | c::DNS_ERROR_RECORD_TIMED_OUT + | c::ERROR_IPSEC_IKE_TIMED_OUT + | c::ERROR_RUNLEVEL_SWITCH_TIMEOUT + | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return TimedOut, + c::ERROR_CALL_NOT_IMPLEMENTED => return Unsupported, + c::ERROR_HOST_UNREACHABLE => return HostUnreachable, + c::ERROR_NETWORK_UNREACHABLE => return NetworkUnreachable, + c::ERROR_DIRECTORY => return NotADirectory, + c::ERROR_DIRECTORY_NOT_SUPPORTED => return IsADirectory, + c::ERROR_DIR_NOT_EMPTY => return DirectoryNotEmpty, + c::ERROR_WRITE_PROTECT => return ReadOnlyFilesystem, + c::ERROR_DISK_FULL | c::ERROR_HANDLE_DISK_FULL => return StorageFull, + c::ERROR_SEEK_ON_DEVICE => return NotSeekable, + c::ERROR_DISK_QUOTA_EXCEEDED => return QuotaExceeded, + c::ERROR_FILE_TOO_LARGE => return FileTooLarge, + c::ERROR_BUSY => return ResourceBusy, + c::ERROR_POSSIBLE_DEADLOCK => return Deadlock, + c::ERROR_NOT_SAME_DEVICE => return CrossesDevices, + c::ERROR_TOO_MANY_LINKS => return TooManyLinks, + c::ERROR_FILENAME_EXCED_RANGE => return InvalidFilename, + c::ERROR_CANT_RESOLVE_FILENAME => return FilesystemLoop, + _ => {} + } + + match errno { + c::WSAEACCES => PermissionDenied, + c::WSAEADDRINUSE => AddrInUse, + c::WSAEADDRNOTAVAIL => AddrNotAvailable, + c::WSAECONNABORTED => ConnectionAborted, + c::WSAECONNREFUSED => ConnectionRefused, + c::WSAECONNRESET => ConnectionReset, + c::WSAEINVAL => InvalidInput, + c::WSAENOTCONN => NotConnected, + c::WSAEWOULDBLOCK => WouldBlock, + c::WSAETIMEDOUT => TimedOut, + c::WSAEHOSTUNREACH => HostUnreachable, + c::WSAENETDOWN => NetworkDown, + c::WSAENETUNREACH => NetworkUnreachable, + c::WSAEDQUOT => QuotaExceeded, + + _ => Uncategorized, + } +} + +/// Gets a detailed string description for the given error number. +pub fn error_string(mut errnum: i32) -> String { + let mut buf = [0 as c::WCHAR; 2048]; + + unsafe { + let mut module = ptr::null_mut(); + let mut flags = 0; + + // NTSTATUS errors may be encoded as HRESULT, which may returned from + // GetLastError. For more information about Windows error codes, see + // `[MS-ERREF]`: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/0642cb2f-2075-4469-918c-4441e69c548a + if (errnum & c::FACILITY_NT_BIT as i32) != 0 { + // format according to https://support.microsoft.com/en-us/help/259693 + const NTDLL_DLL: &[u16] = &[ + 'N' as _, 'T' as _, 'D' as _, 'L' as _, 'L' as _, '.' as _, 'D' as _, 'L' as _, + 'L' as _, 0, + ]; + module = c::GetModuleHandleW(NTDLL_DLL.as_ptr()); + + if !module.is_null() { + errnum ^= c::FACILITY_NT_BIT as i32; + flags = c::FORMAT_MESSAGE_FROM_HMODULE; + } + } + + let res = c::FormatMessageW( + flags | c::FORMAT_MESSAGE_FROM_SYSTEM | c::FORMAT_MESSAGE_IGNORE_INSERTS, + module, + errnum as u32, + 0, + buf.as_mut_ptr(), + buf.len() as u32, + ptr::null(), + ) as usize; + if res == 0 { + // Sometimes FormatMessageW can fail e.g., system doesn't like 0 as langId, + let fm_err = errno(); + return format!("OS Error {errnum} (FormatMessageW() returned error {fm_err})"); + } + + match String::from_utf16(&buf[..res]) { + Ok(mut msg) => { + // Trim trailing CRLF inserted by FormatMessageW + let len = msg.trim_end().len(); + msg.truncate(len); + msg + } + Err(..) => format!( + "OS Error {} (FormatMessageW() returned \ + invalid UTF-16)", + errnum + ), + } + } +} diff --git a/library/std/src/sys/io/error/xous.rs b/library/std/src/sys/io/error/xous.rs new file mode 100644 index 0000000000000..2e9ea8e4f0928 --- /dev/null +++ b/library/std/src/sys/io/error/xous.rs @@ -0,0 +1,17 @@ +use crate::os::xous::ffi::Error as XousError; + +pub fn errno() -> i32 { + 0 +} + +pub fn is_interrupted(_code: i32) -> bool { + false +} + +pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { + crate::io::ErrorKind::Uncategorized +} + +pub fn error_string(errno: i32) -> String { + Into::::into(errno).to_string() +} diff --git a/library/std/src/sys/io/mod.rs b/library/std/src/sys/io/mod.rs index 4a5d6f8e27f25..b3587ab63696a 100644 --- a/library/std/src/sys/io/mod.rs +++ b/library/std/src/sys/io/mod.rs @@ -1,5 +1,7 @@ #![forbid(unsafe_op_in_unsafe_fn)] +mod error; + mod io_slice { cfg_select! { any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3", target_os = "trusty", target_os = "wasi") => { @@ -48,6 +50,19 @@ mod is_terminal { mod kernel_copy; +#[cfg_attr(not(target_os = "linux"), allow(unused_imports))] +#[cfg(all( + target_family = "unix", + not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")) +))] +pub use error::errno_location; +#[cfg_attr(not(target_os = "linux"), allow(unused_imports))] +#[cfg(any( + all(target_family = "unix", not(any(target_os = "vxworks", target_os = "rtems"))), + target_os = "wasi", +))] +pub use error::set_errno; +pub use error::{RawOsError, decode_error_kind, errno, error_string, is_interrupted}; pub use io_slice::{IoSlice, IoSliceMut}; pub use is_terminal::is_terminal; pub use kernel_copy::{CopyState, kernel_copy}; @@ -55,8 +70,3 @@ pub use kernel_copy::{CopyState, kernel_copy}; // Bare metal platforms usually have very small amounts of RAM // (in the order of hundreds of KB) pub const DEFAULT_BUF_SIZE: usize = if cfg!(target_os = "espidf") { 512 } else { 8 * 1024 }; - -pub type RawOsError = cfg_select! { - target_os = "uefi" => usize, - _ => i32, -}; diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs index d09ba97cfe012..5e20c0ffdfa6a 100644 --- a/library/std/src/sys/net/connection/socket/unix.rs +++ b/library/std/src/sys/net/connection/socket/unix.rs @@ -151,7 +151,7 @@ impl Socket { loop { let result = unsafe { libc::connect(self.as_raw_fd(), addr.as_ptr(), len) }; if result.is_minus_one() { - let err = crate::sys::os::errno(); + let err = crate::sys::io::errno(); match err { libc::EINTR => continue, libc::EISCONN => return Ok(()), diff --git a/library/std/src/sys/net/hostname/unix.rs b/library/std/src/sys/net/hostname/unix.rs index bc6fa82a38f0d..d444182f3fde6 100644 --- a/library/std/src/sys/net/hostname/unix.rs +++ b/library/std/src/sys/net/hostname/unix.rs @@ -1,7 +1,7 @@ use crate::ffi::OsString; use crate::io; use crate::os::unix::ffi::OsStringExt; -use crate::sys::pal::os::errno; +use crate::sys::io::errno; pub fn hostname() -> io::Result { // Query the system for the maximum host name length. diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 0e1328a7972f8..db64f8d882e24 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -75,32 +75,6 @@ pub unsafe extern "C" fn runtime_entry( } } -#[inline] -pub(crate) fn is_interrupted(errno: i32) -> bool { - errno == hermit_abi::errno::EINTR -} - -pub fn decode_error_kind(errno: i32) -> io::ErrorKind { - match errno { - hermit_abi::errno::EACCES => io::ErrorKind::PermissionDenied, - hermit_abi::errno::EADDRINUSE => io::ErrorKind::AddrInUse, - hermit_abi::errno::EADDRNOTAVAIL => io::ErrorKind::AddrNotAvailable, - hermit_abi::errno::EAGAIN => io::ErrorKind::WouldBlock, - hermit_abi::errno::ECONNABORTED => io::ErrorKind::ConnectionAborted, - hermit_abi::errno::ECONNREFUSED => io::ErrorKind::ConnectionRefused, - hermit_abi::errno::ECONNRESET => io::ErrorKind::ConnectionReset, - hermit_abi::errno::EEXIST => io::ErrorKind::AlreadyExists, - hermit_abi::errno::EINTR => io::ErrorKind::Interrupted, - hermit_abi::errno::EINVAL => io::ErrorKind::InvalidInput, - hermit_abi::errno::ENOENT => io::ErrorKind::NotFound, - hermit_abi::errno::ENOTCONN => io::ErrorKind::NotConnected, - hermit_abi::errno::EPERM => io::ErrorKind::PermissionDenied, - hermit_abi::errno::EPIPE => io::ErrorKind::BrokenPipe, - hermit_abi::errno::ETIMEDOUT => io::ErrorKind::TimedOut, - _ => io::ErrorKind::Uncategorized, - } -} - #[doc(hidden)] pub trait IsNegative { fn is_negative(&self) -> bool; @@ -131,12 +105,7 @@ impl IsNegative for i32 { impl_is_negative! { i8 i16 i64 isize } pub fn cvt(t: T) -> io::Result { - if t.is_negative() { - let e = decode_error_kind(t.negate()); - Err(io::Error::from(e)) - } else { - Ok(t) - } + if t.is_negative() { Err(io::Error::from_raw_os_error(t.negate())) } else { Ok(t) } } pub fn cvt_r(mut f: F) -> io::Result diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs index 9681964ed9b2f..48a7cdcd2f763 100644 --- a/library/std/src/sys/pal/hermit/os.rs +++ b/library/std/src/sys/pal/hermit/os.rs @@ -5,14 +5,6 @@ use crate::path::{self, PathBuf}; use crate::sys::unsupported; use crate::{fmt, io}; -pub fn errno() -> i32 { - unsafe { hermit_abi::get_errno() } -} - -pub fn error_string(errno: i32) -> String { - hermit_abi::error_string(errno).to_string() -} - pub fn getcwd() -> io::Result { Ok(PathBuf::from("/")) } diff --git a/library/std/src/sys/pal/motor/mod.rs b/library/std/src/sys/pal/motor/mod.rs index 016fbe5c154c9..e5b99cea01d55 100644 --- a/library/std/src/sys/pal/motor/mod.rs +++ b/library/std/src/sys/pal/motor/mod.rs @@ -44,45 +44,6 @@ pub fn unsupported_err() -> io::Error { io::Error::UNSUPPORTED_PLATFORM } -pub fn is_interrupted(_code: io::RawOsError) -> bool { - false // Motor OS doesn't have signals. -} - -pub fn decode_error_kind(code: io::RawOsError) -> io::ErrorKind { - use moto_rt::error::*; - - if code < 0 || code > u16::MAX.into() { - return io::ErrorKind::Uncategorized; - } - - let error = moto_rt::Error::from(code as moto_rt::ErrorCode); - - match error { - moto_rt::Error::Unspecified => io::ErrorKind::Uncategorized, - moto_rt::Error::Unknown => io::ErrorKind::Uncategorized, - moto_rt::Error::NotReady => io::ErrorKind::WouldBlock, - moto_rt::Error::NotImplemented => io::ErrorKind::Unsupported, - moto_rt::Error::VersionTooHigh => io::ErrorKind::Unsupported, - moto_rt::Error::VersionTooLow => io::ErrorKind::Unsupported, - moto_rt::Error::InvalidArgument => io::ErrorKind::InvalidInput, - moto_rt::Error::OutOfMemory => io::ErrorKind::OutOfMemory, - moto_rt::Error::NotAllowed => io::ErrorKind::PermissionDenied, - moto_rt::Error::NotFound => io::ErrorKind::NotFound, - moto_rt::Error::InternalError => io::ErrorKind::Other, - moto_rt::Error::TimedOut => io::ErrorKind::TimedOut, - moto_rt::Error::AlreadyInUse => io::ErrorKind::AlreadyExists, - moto_rt::Error::UnexpectedEof => io::ErrorKind::UnexpectedEof, - moto_rt::Error::InvalidFilename => io::ErrorKind::InvalidFilename, - moto_rt::Error::NotADirectory => io::ErrorKind::NotADirectory, - moto_rt::Error::BadHandle => io::ErrorKind::InvalidInput, - moto_rt::Error::FileTooLarge => io::ErrorKind::FileTooLarge, - moto_rt::Error::NotConnected => io::ErrorKind::NotConnected, - moto_rt::Error::StorageFull => io::ErrorKind::StorageFull, - moto_rt::Error::InvalidData => io::ErrorKind::InvalidData, - _ => io::ErrorKind::Uncategorized, - } -} - pub fn abort_internal() -> ! { core::intrinsics::abort(); } diff --git a/library/std/src/sys/pal/motor/os.rs b/library/std/src/sys/pal/motor/os.rs index 0367c905b4535..cdf66e3958dbe 100644 --- a/library/std/src/sys/pal/motor/os.rs +++ b/library/std/src/sys/pal/motor/os.rs @@ -4,37 +4,8 @@ use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; use crate::os::motor::ffi::OsStrExt; use crate::path::{self, PathBuf}; -use crate::sys::io::RawOsError; use crate::{fmt, io}; -pub fn errno() -> RawOsError { - // Not used in Motor OS because it is ambiguous: Motor OS - // is micro-kernel-based, and I/O happens via a shared-memory - // ring buffer, so an I/O operation that on a unix is a syscall - // may involve no sycalls on Motor OS at all, or a syscall - // that e.g. waits for a notification from the I/O driver - // (sys-io); and the wait syscall may succeed, but the - // driver may report an I/O error; or a bunch of results - // for several I/O operations, some successful and some - // not. - // - // Also I/O operations in a Motor OS process are handled by a - // separate runtime background/I/O thread, so it is really hard - // to define what "last system error in the current thread" - // actually means. - let error_code: moto_rt::ErrorCode = moto_rt::Error::Unknown.into(); - error_code.into() -} - -pub fn error_string(errno: RawOsError) -> String { - let error: moto_rt::Error = match errno { - x if x < 0 => moto_rt::Error::Unknown, - x if x > u16::MAX.into() => moto_rt::Error::Unknown, - x => (x as moto_rt::ErrorCode).into(), /* u16 */ - }; - format!("{}", error) -} - pub fn getcwd() -> io::Result { moto_rt::fs::getcwd().map(PathBuf::from).map_err(map_motor_error) } diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index a067480508c7c..7f1c81a0ff7bf 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -54,56 +54,6 @@ pub fn sgx_ineffective(v: T) -> io::Result { } } -#[inline] -pub fn is_interrupted(code: i32) -> bool { - code == fortanix_sgx_abi::Error::Interrupted as _ -} - -pub fn decode_error_kind(code: i32) -> io::ErrorKind { - use fortanix_sgx_abi::Error; - - // FIXME: not sure how to make sure all variants of Error are covered - if code == Error::NotFound as _ { - io::ErrorKind::NotFound - } else if code == Error::PermissionDenied as _ { - io::ErrorKind::PermissionDenied - } else if code == Error::ConnectionRefused as _ { - io::ErrorKind::ConnectionRefused - } else if code == Error::ConnectionReset as _ { - io::ErrorKind::ConnectionReset - } else if code == Error::ConnectionAborted as _ { - io::ErrorKind::ConnectionAborted - } else if code == Error::NotConnected as _ { - io::ErrorKind::NotConnected - } else if code == Error::AddrInUse as _ { - io::ErrorKind::AddrInUse - } else if code == Error::AddrNotAvailable as _ { - io::ErrorKind::AddrNotAvailable - } else if code == Error::BrokenPipe as _ { - io::ErrorKind::BrokenPipe - } else if code == Error::AlreadyExists as _ { - io::ErrorKind::AlreadyExists - } else if code == Error::WouldBlock as _ { - io::ErrorKind::WouldBlock - } else if code == Error::InvalidInput as _ { - io::ErrorKind::InvalidInput - } else if code == Error::InvalidData as _ { - io::ErrorKind::InvalidData - } else if code == Error::TimedOut as _ { - io::ErrorKind::TimedOut - } else if code == Error::WriteZero as _ { - io::ErrorKind::WriteZero - } else if code == Error::Interrupted as _ { - io::ErrorKind::Interrupted - } else if code == Error::Other as _ { - io::ErrorKind::Uncategorized - } else if code == Error::UnexpectedEof as _ { - io::ErrorKind::UnexpectedEof - } else { - io::ErrorKind::Uncategorized - } -} - pub fn abort_internal() -> ! { abi::usercalls::exit(true) } diff --git a/library/std/src/sys/pal/sgx/os.rs b/library/std/src/sys/pal/sgx/os.rs index 28d79963ac874..ba47af7ff88d7 100644 --- a/library/std/src/sys/pal/sgx/os.rs +++ b/library/std/src/sys/pal/sgx/os.rs @@ -1,25 +1,9 @@ -use fortanix_sgx_abi::{Error, RESULT_SUCCESS}; - use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; use crate::path::{self, PathBuf}; -use crate::sys::{decode_error_kind, sgx_ineffective, unsupported}; +use crate::sys::{sgx_ineffective, unsupported}; use crate::{fmt, io}; -pub fn errno() -> i32 { - RESULT_SUCCESS -} - -pub fn error_string(errno: i32) -> String { - if errno == RESULT_SUCCESS { - "operation successful".into() - } else if ((Error::UserRangeStart as _)..=(Error::UserRangeEnd as _)).contains(&errno) { - format!("user-specified error {errno:08x}") - } else { - decode_error_kind(errno).as_str().into() - } -} - pub fn getcwd() -> io::Result { unsupported() } diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index 01477c7dc5e9b..4eec12dacd7ca 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -38,15 +38,6 @@ pub fn unsupported_err() -> io::Error { io::Error::UNSUPPORTED_PLATFORM } -#[inline] -pub fn is_interrupted(code: i32) -> bool { - crate::sys::net::is_interrupted(code) -} - -pub fn decode_error_kind(code: i32) -> io::ErrorKind { - error::decode_error_kind(code) -} - #[inline] pub fn abort_internal() -> ! { unsafe { libc::abort() } diff --git a/library/std/src/sys/pal/solid/os.rs b/library/std/src/sys/pal/solid/os.rs index cb6e2cbceae6c..c336a1042da40 100644 --- a/library/std/src/sys/pal/solid/os.rs +++ b/library/std/src/sys/pal/solid/os.rs @@ -1,4 +1,4 @@ -use super::{error, itron, unsupported}; +use super::{itron, unsupported}; use crate::ffi::{OsStr, OsString}; use crate::path::{self, PathBuf}; use crate::{fmt, io}; @@ -11,14 +11,6 @@ impl itron::error::ItronError { } } -pub fn errno() -> i32 { - 0 -} - -pub fn error_string(errno: i32) -> String { - if let Some(name) = error::error_name(errno) { name.to_owned() } else { format!("{errno}") } -} - pub fn getcwd() -> io::Result { unsupported() } diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index 627096b11c388..d40c10663fd17 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -38,61 +38,6 @@ pub unsafe fn cleanup() { // stack_overflow::cleanup(); } -#[inline] -pub(crate) fn is_interrupted(errno: i32) -> bool { - errno == libc::EINTR -} - -// Note: code below is 1:1 copied from unix/mod.rs -pub fn decode_error_kind(errno: i32) -> io::ErrorKind { - use io::ErrorKind::*; - match errno as libc::c_int { - libc::E2BIG => ArgumentListTooLong, - libc::EADDRINUSE => AddrInUse, - libc::EADDRNOTAVAIL => AddrNotAvailable, - libc::EBUSY => ResourceBusy, - libc::ECONNABORTED => ConnectionAborted, - libc::ECONNREFUSED => ConnectionRefused, - libc::ECONNRESET => ConnectionReset, - libc::EDEADLK => Deadlock, - libc::EDQUOT => QuotaExceeded, - libc::EEXIST => AlreadyExists, - libc::EFBIG => FileTooLarge, - libc::EHOSTUNREACH => HostUnreachable, - libc::EINTR => Interrupted, - libc::EINVAL => InvalidInput, - libc::EISDIR => IsADirectory, - libc::ELOOP => FilesystemLoop, - libc::ENOENT => NotFound, - libc::ENOMEM => OutOfMemory, - libc::ENOSPC => StorageFull, - libc::ENOSYS => Unsupported, - libc::EMLINK => TooManyLinks, - libc::ENAMETOOLONG => InvalidFilename, - libc::ENETDOWN => NetworkDown, - libc::ENETUNREACH => NetworkUnreachable, - libc::ENOTCONN => NotConnected, - libc::ENOTDIR => NotADirectory, - libc::ENOTEMPTY => DirectoryNotEmpty, - libc::EPIPE => BrokenPipe, - libc::EROFS => ReadOnlyFilesystem, - libc::ESPIPE => NotSeekable, - libc::ESTALE => StaleNetworkFileHandle, - libc::ETIMEDOUT => TimedOut, - libc::ETXTBSY => ExecutableFileBusy, - libc::EXDEV => CrossesDevices, - - libc::EACCES | libc::EPERM => PermissionDenied, - - // These two constants can have the same value on some systems, - // but different values on others, so we can't use a match - // clause - x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock, - - _ => Uncategorized, - } -} - #[doc(hidden)] pub trait IsMinusOne { fn is_minus_one(&self) -> bool; diff --git a/library/std/src/sys/pal/teeos/os.rs b/library/std/src/sys/pal/teeos/os.rs index 512b3e2885bf0..a4b1d3c6ae670 100644 --- a/library/std/src/sys/pal/teeos/os.rs +++ b/library/std/src/sys/pal/teeos/os.rs @@ -7,10 +7,6 @@ use crate::ffi::{OsStr, OsString}; use crate::path::PathBuf; use crate::{fmt, io, path}; -pub fn errno() -> i32 { - unsafe { (*libc::__errno_location()) as i32 } -} - // Hardcoded to return 4096, since `sysconf` is only implemented as a stub. pub fn page_size() -> usize { // unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }; @@ -19,10 +15,6 @@ pub fn page_size() -> usize { // Everything below are stubs and copied from unsupported.rs -pub fn error_string(_errno: i32) -> String { - "error string unimplemented".to_string() -} - pub fn getcwd() -> io::Result { unsupported() } diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index e2f99d6751f5e..b181d78c2345a 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -83,52 +83,6 @@ pub const fn unsupported_err() -> io::Error { io::const_error!(io::ErrorKind::Unsupported, "operation not supported on UEFI") } -pub fn decode_error_kind(code: io::RawOsError) -> io::ErrorKind { - use r_efi::efi::Status; - - match r_efi::efi::Status::from_usize(code) { - Status::ALREADY_STARTED - | Status::COMPROMISED_DATA - | Status::CONNECTION_FIN - | Status::CRC_ERROR - | Status::DEVICE_ERROR - | Status::END_OF_MEDIA - | Status::HTTP_ERROR - | Status::ICMP_ERROR - | Status::INCOMPATIBLE_VERSION - | Status::LOAD_ERROR - | Status::MEDIA_CHANGED - | Status::NO_MAPPING - | Status::NO_MEDIA - | Status::NOT_STARTED - | Status::PROTOCOL_ERROR - | Status::PROTOCOL_UNREACHABLE - | Status::TFTP_ERROR - | Status::VOLUME_CORRUPTED => io::ErrorKind::Other, - Status::BAD_BUFFER_SIZE | Status::INVALID_LANGUAGE => io::ErrorKind::InvalidData, - Status::ABORTED => io::ErrorKind::ConnectionAborted, - Status::ACCESS_DENIED => io::ErrorKind::PermissionDenied, - Status::BUFFER_TOO_SMALL => io::ErrorKind::FileTooLarge, - Status::CONNECTION_REFUSED => io::ErrorKind::ConnectionRefused, - Status::CONNECTION_RESET => io::ErrorKind::ConnectionReset, - Status::END_OF_FILE => io::ErrorKind::UnexpectedEof, - Status::HOST_UNREACHABLE => io::ErrorKind::HostUnreachable, - Status::INVALID_PARAMETER => io::ErrorKind::InvalidInput, - Status::IP_ADDRESS_CONFLICT => io::ErrorKind::AddrInUse, - Status::NETWORK_UNREACHABLE => io::ErrorKind::NetworkUnreachable, - Status::NO_RESPONSE => io::ErrorKind::HostUnreachable, - Status::NOT_FOUND => io::ErrorKind::NotFound, - Status::NOT_READY => io::ErrorKind::ResourceBusy, - Status::OUT_OF_RESOURCES => io::ErrorKind::OutOfMemory, - Status::SECURITY_VIOLATION => io::ErrorKind::PermissionDenied, - Status::TIMEOUT => io::ErrorKind::TimedOut, - Status::UNSUPPORTED => io::ErrorKind::Unsupported, - Status::VOLUME_FULL => io::ErrorKind::StorageFull, - Status::WRITE_PROTECTED => io::ErrorKind::ReadOnlyFilesystem, - _ => io::ErrorKind::Uncategorized, - } -} - pub fn abort_internal() -> ! { if let Some(exit_boot_service_event) = NonNull::new(EXIT_BOOT_SERVICE_EVENT.load(Ordering::Acquire)) @@ -158,7 +112,3 @@ pub fn abort_internal() -> ! { extern "efiapi" fn exit_boot_service_handler(_e: r_efi::efi::Event, _ctx: *mut crate::ffi::c_void) { uefi::env::disable_boot_services(); } - -pub fn is_interrupted(_code: io::RawOsError) -> bool { - false -} diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs index 5593e195178de..178f7f506341e 100644 --- a/library/std/src/sys/pal/uefi/os.rs +++ b/library/std/src/sys/pal/uefi/os.rs @@ -9,59 +9,6 @@ use crate::path::{self, PathBuf}; use crate::ptr::NonNull; use crate::{fmt, io}; -pub fn errno() -> io::RawOsError { - 0 -} - -pub fn error_string(errno: io::RawOsError) -> String { - // Keep the List in Alphabetical Order - // The Messages are taken from UEFI Specification Appendix D - Status Codes - #[rustfmt::skip] - let msg = match r_efi::efi::Status::from_usize(errno) { - Status::ABORTED => "The operation was aborted.", - Status::ACCESS_DENIED => "Access was denied.", - Status::ALREADY_STARTED => "The protocol has already been started.", - Status::BAD_BUFFER_SIZE => "The buffer was not the proper size for the request.", - Status::BUFFER_TOO_SMALL => "The buffer is not large enough to hold the requested data. The required buffer size is returned in the appropriate parameter when this error occurs.", - Status::COMPROMISED_DATA => "The security status of the data is unknown or compromised and the data must be updated or replaced to restore a valid security status.", - Status::CONNECTION_FIN => "The receiving operation fails because the communication peer has closed the connection and there is no more data in the receive buffer of the instance.", - Status::CONNECTION_REFUSED => "The receiving or transmission operation fails because this connection is refused.", - Status::CONNECTION_RESET => "The connect fails because the connection is reset either by instance itself or the communication peer.", - Status::CRC_ERROR => "A CRC error was detected.", - Status::DEVICE_ERROR => "The physical device reported an error while attempting the operation.", - Status::END_OF_FILE => "The end of the file was reached.", - Status::END_OF_MEDIA => "Beginning or end of media was reached", - Status::HOST_UNREACHABLE => "The remote host is not reachable.", - Status::HTTP_ERROR => "A HTTP error occurred during the network operation.", - Status::ICMP_ERROR => "An ICMP error occurred during the network operation.", - Status::INCOMPATIBLE_VERSION => "The function encountered an internal version that was incompatible with a version requested by the caller.", - Status::INVALID_LANGUAGE => "The language specified was invalid.", - Status::INVALID_PARAMETER => "A parameter was incorrect.", - Status::IP_ADDRESS_CONFLICT => "There is an address conflict address allocation", - Status::LOAD_ERROR => "The image failed to load.", - Status::MEDIA_CHANGED => "The medium in the device has changed since the last access.", - Status::NETWORK_UNREACHABLE => "The network containing the remote host is not reachable.", - Status::NO_MAPPING => "A mapping to a device does not exist.", - Status::NO_MEDIA => "The device does not contain any medium to perform the operation.", - Status::NO_RESPONSE => "The server was not found or did not respond to the request.", - Status::NOT_FOUND => "The item was not found.", - Status::NOT_READY => "There is no data pending upon return.", - Status::NOT_STARTED => "The protocol has not been started.", - Status::OUT_OF_RESOURCES => "A resource has run out.", - Status::PROTOCOL_ERROR => "A protocol error occurred during the network operation.", - Status::PROTOCOL_UNREACHABLE => "An ICMP protocol unreachable error is received.", - Status::SECURITY_VIOLATION => "The function was not performed due to a security violation.", - Status::TFTP_ERROR => "A TFTP error occurred during the network operation.", - Status::TIMEOUT => "The timeout time expired.", - Status::UNSUPPORTED => "The operation is not supported.", - Status::VOLUME_FULL => "There is no more space on the file system.", - Status::VOLUME_CORRUPTED => "An inconstancy was detected on the file system causing the operating to fail.", - Status::WRITE_PROTECTED => "The device cannot be written to.", - _ => return format!("Status: {errno}"), - }; - msg.to_owned() -} - pub fn getcwd() -> io::Result { match helpers::open_shell() { Some(shell) => { diff --git a/library/std/src/sys/pal/unix/futex.rs b/library/std/src/sys/pal/unix/futex.rs index 265067d84d502..2948d3d594eaa 100644 --- a/library/std/src/sys/pal/unix/futex.rs +++ b/library/std/src/sys/pal/unix/futex.rs @@ -86,7 +86,7 @@ pub fn futex_wait(futex: &Atomic, expected: u32, timeout: Option) } }; - match (r < 0).then(super::os::errno) { + match (r < 0).then(crate::sys::io::errno) { Some(libc::ETIMEDOUT) => return false, Some(libc::EINTR) => continue, _ => return true, @@ -167,7 +167,7 @@ pub fn futex_wait(futex: &Atomic, expected: u32, timeout: Option) ) }; - r == 0 || super::os::errno() != libc::ETIMEDOUT + r == 0 || crate::sys::io::errno() != libc::ETIMEDOUT } #[cfg(target_os = "openbsd")] @@ -210,7 +210,7 @@ pub fn futex_wait(futex: &Atomic, expected: u32, timeout: Option) libc::umtx_sleep(futex as *const Atomic as *const i32, expected as i32, timeout_ms) }; - r == 0 || super::os::errno() != libc::ETIMEDOUT + r == 0 || crate::sys::io::errno() != libc::ETIMEDOUT } // DragonflyBSD doesn't tell us how many threads are woken up, so this always returns false. diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index f24898671af82..6127bb98f80ef 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -91,7 +91,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_vendor = "apple", )))] 'poll: { - use crate::sys::os::errno; + use crate::sys::io::errno; let pfds: &mut [_] = &mut [ libc::pollfd { fd: 0, events: 0, revents: 0 }, libc::pollfd { fd: 1, events: 0, revents: 0 }, @@ -135,7 +135,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_os = "vita", )))] { - use crate::sys::os::errno; + use crate::sys::io::errno; for fd in 0..3 { if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF { open_devnull(); @@ -224,63 +224,6 @@ pub unsafe fn cleanup() { #[allow(unused_imports)] pub use libc::signal; -#[inline] -pub(crate) fn is_interrupted(errno: i32) -> bool { - errno == libc::EINTR -} - -pub fn decode_error_kind(errno: i32) -> io::ErrorKind { - use io::ErrorKind::*; - match errno as libc::c_int { - libc::E2BIG => ArgumentListTooLong, - libc::EADDRINUSE => AddrInUse, - libc::EADDRNOTAVAIL => AddrNotAvailable, - libc::EBUSY => ResourceBusy, - libc::ECONNABORTED => ConnectionAborted, - libc::ECONNREFUSED => ConnectionRefused, - libc::ECONNRESET => ConnectionReset, - libc::EDEADLK => Deadlock, - libc::EDQUOT => QuotaExceeded, - libc::EEXIST => AlreadyExists, - libc::EFBIG => FileTooLarge, - libc::EHOSTUNREACH => HostUnreachable, - libc::EINTR => Interrupted, - libc::EINVAL => InvalidInput, - libc::EISDIR => IsADirectory, - libc::ELOOP => FilesystemLoop, - libc::ENOENT => NotFound, - libc::ENOMEM => OutOfMemory, - libc::ENOSPC => StorageFull, - libc::ENOSYS => Unsupported, - libc::EMLINK => TooManyLinks, - libc::ENAMETOOLONG => InvalidFilename, - libc::ENETDOWN => NetworkDown, - libc::ENETUNREACH => NetworkUnreachable, - libc::ENOTCONN => NotConnected, - libc::ENOTDIR => NotADirectory, - #[cfg(not(target_os = "aix"))] - libc::ENOTEMPTY => DirectoryNotEmpty, - libc::EPIPE => BrokenPipe, - libc::EROFS => ReadOnlyFilesystem, - libc::ESPIPE => NotSeekable, - libc::ESTALE => StaleNetworkFileHandle, - libc::ETIMEDOUT => TimedOut, - libc::ETXTBSY => ExecutableFileBusy, - libc::EXDEV => CrossesDevices, - libc::EINPROGRESS => InProgress, - libc::EOPNOTSUPP => Unsupported, - - libc::EACCES | libc::EPERM => PermissionDenied, - - // These two constants can have the same value on some systems, - // but different values on others, so we can't use a match - // clause - x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock, - - _ => Uncategorized, - } -} - #[doc(hidden)] pub trait IsMinusOne { fn is_minus_one(&self) -> bool; diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index ef3b4a02f8ae4..b8280a8f29a02 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -14,135 +14,8 @@ use crate::sys::cvt; use crate::sys::helpers::run_path_with_cstr; use crate::{fmt, io, iter, mem, ptr, slice, str}; -const TMPBUF_SZ: usize = 128; - const PATH_SEPARATOR: u8 = b':'; -unsafe extern "C" { - #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] - #[cfg_attr( - any( - target_os = "linux", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "l4re", - target_os = "hurd", - ), - link_name = "__errno_location" - )] - #[cfg_attr( - any( - target_os = "netbsd", - target_os = "openbsd", - target_os = "cygwin", - target_os = "android", - target_os = "redox", - target_os = "nuttx", - target_env = "newlib" - ), - link_name = "__errno" - )] - #[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")] - #[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")] - #[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")] - #[cfg_attr(target_os = "haiku", link_name = "_errnop")] - #[cfg_attr(target_os = "aix", link_name = "_Errno")] - // SAFETY: this will always return the same pointer on a given thread. - #[unsafe(ffi_const)] - pub safe fn errno_location() -> *mut c_int; -} - -/// Returns the platform-specific value of errno -#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] -#[inline] -pub fn errno() -> i32 { - unsafe { (*errno_location()) as i32 } -} - -/// Sets the platform-specific value of errno -// needed for readdir and syscall! -#[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks"), not(target_os = "rtems")))] -#[allow(dead_code)] // but not all target cfgs actually end up using it -#[inline] -pub fn set_errno(e: i32) { - unsafe { *errno_location() = e as c_int } -} - -#[cfg(target_os = "vxworks")] -#[inline] -pub fn errno() -> i32 { - unsafe { libc::errnoGet() } -} - -#[cfg(target_os = "rtems")] -#[inline] -pub fn errno() -> i32 { - unsafe extern "C" { - #[thread_local] - static _tls_errno: c_int; - } - - unsafe { _tls_errno as i32 } -} - -#[cfg(target_os = "dragonfly")] -#[inline] -pub fn errno() -> i32 { - unsafe extern "C" { - #[thread_local] - static errno: c_int; - } - - unsafe { errno as i32 } -} - -#[cfg(target_os = "dragonfly")] -#[allow(dead_code)] -#[inline] -pub fn set_errno(e: i32) { - unsafe extern "C" { - #[thread_local] - static mut errno: c_int; - } - - unsafe { - errno = e; - } -} - -/// Gets a detailed string description for the given error number. -pub fn error_string(errno: i32) -> String { - unsafe extern "C" { - #[cfg_attr( - all( - any( - target_os = "linux", - target_os = "hurd", - target_env = "newlib", - target_os = "cygwin" - ), - not(target_env = "ohos") - ), - link_name = "__xpg_strerror_r" - )] - fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) -> c_int; - } - - let mut buf = [0 as c_char; TMPBUF_SZ]; - - let p = buf.as_mut_ptr(); - unsafe { - if strerror_r(errno as c_int, p, buf.len()) < 0 { - panic!("strerror_r failure"); - } - - let p = p as *const _; - // We can't always expect a UTF-8 environment. When we don't get that luxury, - // it's better to give a low-quality error message than none at all. - String::from_utf8_lossy(CStr::from_ptr(p).to_bytes()).into() - } -} - #[cfg(target_os = "espidf")] pub fn getcwd() -> io::Result { Ok(PathBuf::from("/")) diff --git a/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs b/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs index 42eb0cd9a61af..45e2f09f303cd 100644 --- a/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs +++ b/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs @@ -29,7 +29,7 @@ use crate::hint::spin_loop; use crate::ops::Range; use crate::sync::Mutex; use crate::sync::atomic::{AtomicUsize, Ordering}; -use crate::sys::os::errno_location; +use crate::sys::io::errno_location; pub struct ThreadInfo { pub tid: u64, diff --git a/library/std/src/sys/pal/unsupported/common.rs b/library/std/src/sys/pal/unsupported/common.rs index 34a766683830d..d94b9015d0f5f 100644 --- a/library/std/src/sys/pal/unsupported/common.rs +++ b/library/std/src/sys/pal/unsupported/common.rs @@ -16,14 +16,6 @@ pub fn unsupported_err() -> std_io::Error { std_io::Error::UNSUPPORTED_PLATFORM } -pub fn is_interrupted(_code: i32) -> bool { - false -} - -pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { - crate::io::ErrorKind::Uncategorized -} - pub fn abort_internal() -> ! { core::intrinsics::abort(); } diff --git a/library/std/src/sys/pal/unsupported/os.rs b/library/std/src/sys/pal/unsupported/os.rs index 13d2a2044f48a..cb925ef4348db 100644 --- a/library/std/src/sys/pal/unsupported/os.rs +++ b/library/std/src/sys/pal/unsupported/os.rs @@ -4,14 +4,6 @@ use crate::marker::PhantomData; use crate::path::{self, PathBuf}; use crate::{fmt, io}; -pub fn errno() -> i32 { - 0 -} - -pub fn error_string(_errno: i32) -> String { - "operation successful".to_string() -} - pub fn getcwd() -> io::Result { unsupported() } diff --git a/library/std/src/sys/pal/vexos/mod.rs b/library/std/src/sys/pal/vexos/mod.rs index 049b435905d43..0abfc2fd79865 100644 --- a/library/std/src/sys/pal/vexos/mod.rs +++ b/library/std/src/sys/pal/vexos/mod.rs @@ -5,9 +5,7 @@ pub mod time; #[path = "../unsupported/common.rs"] mod unsupported_common; -pub use unsupported_common::{ - decode_error_kind, init, is_interrupted, unsupported, unsupported_err, -}; +pub use unsupported_common::{init, unsupported, unsupported_err}; use crate::arch::global_asm; use crate::ptr; diff --git a/library/std/src/sys/pal/vexos/os.rs b/library/std/src/sys/pal/vexos/os.rs index 405f7c918f4a5..303b452a078ff 100644 --- a/library/std/src/sys/pal/vexos/os.rs +++ b/library/std/src/sys/pal/vexos/os.rs @@ -2,8 +2,8 @@ #[path = "../unsupported/os.rs"] mod unsupported_os; pub use unsupported_os::{ - JoinPathsError, SplitPaths, chdir, current_exe, errno, error_string, getcwd, getpid, home_dir, - join_paths, split_paths, temp_dir, + JoinPathsError, SplitPaths, chdir, current_exe, getcwd, getpid, home_dir, join_paths, + split_paths, temp_dir, }; pub use super::unsupported; diff --git a/library/std/src/sys/pal/wasi/helpers.rs b/library/std/src/sys/pal/wasi/helpers.rs index 6bc41d469584d..4f2eb1148f0b3 100644 --- a/library/std/src/sys/pal/wasi/helpers.rs +++ b/library/std/src/sys/pal/wasi/helpers.rs @@ -1,63 +1,11 @@ #![forbid(unsafe_op_in_unsafe_fn)] -use crate::io as std_io; - -#[inline] -pub fn is_interrupted(errno: i32) -> bool { - errno == libc::EINTR -} - -pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { - use std_io::ErrorKind::*; - match errno as libc::c_int { - libc::E2BIG => ArgumentListTooLong, - libc::EADDRINUSE => AddrInUse, - libc::EADDRNOTAVAIL => AddrNotAvailable, - libc::EBUSY => ResourceBusy, - libc::ECONNABORTED => ConnectionAborted, - libc::ECONNREFUSED => ConnectionRefused, - libc::ECONNRESET => ConnectionReset, - libc::EDEADLK => Deadlock, - libc::EDQUOT => QuotaExceeded, - libc::EEXIST => AlreadyExists, - libc::EFBIG => FileTooLarge, - libc::EHOSTUNREACH => HostUnreachable, - libc::EINTR => Interrupted, - libc::EINVAL => InvalidInput, - libc::EISDIR => IsADirectory, - libc::ELOOP => FilesystemLoop, - libc::ENOENT => NotFound, - libc::ENOMEM => OutOfMemory, - libc::ENOSPC => StorageFull, - libc::ENOSYS => Unsupported, - libc::EMLINK => TooManyLinks, - libc::ENAMETOOLONG => InvalidFilename, - libc::ENETDOWN => NetworkDown, - libc::ENETUNREACH => NetworkUnreachable, - libc::ENOTCONN => NotConnected, - libc::ENOTDIR => NotADirectory, - libc::EPIPE => BrokenPipe, - libc::EROFS => ReadOnlyFilesystem, - libc::ESPIPE => NotSeekable, - libc::ESTALE => StaleNetworkFileHandle, - libc::ETIMEDOUT => TimedOut, - libc::ETXTBSY => ExecutableFileBusy, - libc::EXDEV => CrossesDevices, - libc::EINPROGRESS => InProgress, - libc::EOPNOTSUPP => Unsupported, - libc::EACCES | libc::EPERM => PermissionDenied, - libc::EWOULDBLOCK => WouldBlock, - - _ => Uncategorized, - } -} - pub fn abort_internal() -> ! { unsafe { libc::abort() } } #[inline] #[cfg(target_env = "p1")] -pub(crate) fn err2io(err: wasi::Errno) -> std_io::Error { - std_io::Error::from_raw_os_error(err.raw().into()) +pub(crate) fn err2io(err: wasi::Errno) -> crate::io::Error { + crate::io::Error::from_raw_os_error(err.raw().into()) } diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index 5d36687df0977..9b49db9af6b05 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -26,9 +26,9 @@ mod helpers; // import conflict rules. If we glob export `helpers` and `common` together, // then the compiler complains about conflicts. +pub(crate) use helpers::abort_internal; #[cfg(target_env = "p1")] pub(crate) use helpers::err2io; -pub(crate) use helpers::{abort_internal, decode_error_kind, is_interrupted}; #[cfg(not(target_env = "p1"))] pub use os::IsMinusOne; pub use os::{cvt, cvt_r}; diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/pal/wasi/os.rs index fee187a8adf3c..285be3ca9fda4 100644 --- a/library/std/src/sys/pal/wasi/os.rs +++ b/library/std/src/sys/pal/wasi/os.rs @@ -6,7 +6,7 @@ use crate::os::wasi::prelude::*; use crate::path::{self, PathBuf}; use crate::sys::helpers::run_path_with_cstr; use crate::sys::unsupported; -use crate::{fmt, io, str}; +use crate::{fmt, io}; // Add a few symbols not in upstream `libc` just yet. pub mod libc { @@ -19,34 +19,6 @@ pub mod libc { } } -unsafe extern "C" { - #[thread_local] - #[link_name = "errno"] - static mut libc_errno: libc::c_int; -} - -pub fn errno() -> i32 { - unsafe { libc_errno as i32 } -} - -pub fn set_errno(val: i32) { - unsafe { - libc_errno = val; - } -} - -pub fn error_string(errno: i32) -> String { - let mut buf = [0 as libc::c_char; 1024]; - - let p = buf.as_mut_ptr(); - unsafe { - if libc::strerror_r(errno as libc::c_int, p, buf.len()) < 0 { - panic!("strerror_r failure"); - } - str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned() - } -} - pub fn getcwd() -> io::Result { let mut buf = Vec::with_capacity(512); loop { diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 19f0259b1bf09..17e3cdbecd5c2 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -60,84 +60,6 @@ pub unsafe fn cleanup() { winsock::cleanup(); } -#[inline] -pub fn is_interrupted(_errno: i32) -> bool { - false -} - -pub fn decode_error_kind(errno: i32) -> io::ErrorKind { - use io::ErrorKind::*; - - match errno as u32 { - c::ERROR_ACCESS_DENIED => return PermissionDenied, - c::ERROR_ALREADY_EXISTS => return AlreadyExists, - c::ERROR_FILE_EXISTS => return AlreadyExists, - c::ERROR_BROKEN_PIPE => return BrokenPipe, - c::ERROR_FILE_NOT_FOUND - | c::ERROR_PATH_NOT_FOUND - | c::ERROR_INVALID_DRIVE - | c::ERROR_BAD_NETPATH - | c::ERROR_BAD_NET_NAME => return NotFound, - c::ERROR_NO_DATA => return BrokenPipe, - c::ERROR_INVALID_NAME | c::ERROR_BAD_PATHNAME => return InvalidFilename, - c::ERROR_INVALID_PARAMETER => return InvalidInput, - c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return OutOfMemory, - c::ERROR_SEM_TIMEOUT - | c::WAIT_TIMEOUT - | c::ERROR_DRIVER_CANCEL_TIMEOUT - | c::ERROR_OPERATION_ABORTED - | c::ERROR_SERVICE_REQUEST_TIMEOUT - | c::ERROR_COUNTER_TIMEOUT - | c::ERROR_TIMEOUT - | c::ERROR_RESOURCE_CALL_TIMED_OUT - | c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT - | c::ERROR_CTX_CLIENT_QUERY_TIMEOUT - | c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT - | c::ERROR_DS_TIMELIMIT_EXCEEDED - | c::DNS_ERROR_RECORD_TIMED_OUT - | c::ERROR_IPSEC_IKE_TIMED_OUT - | c::ERROR_RUNLEVEL_SWITCH_TIMEOUT - | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return TimedOut, - c::ERROR_CALL_NOT_IMPLEMENTED => return Unsupported, - c::ERROR_HOST_UNREACHABLE => return HostUnreachable, - c::ERROR_NETWORK_UNREACHABLE => return NetworkUnreachable, - c::ERROR_DIRECTORY => return NotADirectory, - c::ERROR_DIRECTORY_NOT_SUPPORTED => return IsADirectory, - c::ERROR_DIR_NOT_EMPTY => return DirectoryNotEmpty, - c::ERROR_WRITE_PROTECT => return ReadOnlyFilesystem, - c::ERROR_DISK_FULL | c::ERROR_HANDLE_DISK_FULL => return StorageFull, - c::ERROR_SEEK_ON_DEVICE => return NotSeekable, - c::ERROR_DISK_QUOTA_EXCEEDED => return QuotaExceeded, - c::ERROR_FILE_TOO_LARGE => return FileTooLarge, - c::ERROR_BUSY => return ResourceBusy, - c::ERROR_POSSIBLE_DEADLOCK => return Deadlock, - c::ERROR_NOT_SAME_DEVICE => return CrossesDevices, - c::ERROR_TOO_MANY_LINKS => return TooManyLinks, - c::ERROR_FILENAME_EXCED_RANGE => return InvalidFilename, - c::ERROR_CANT_RESOLVE_FILENAME => return FilesystemLoop, - _ => {} - } - - match errno { - c::WSAEACCES => PermissionDenied, - c::WSAEADDRINUSE => AddrInUse, - c::WSAEADDRNOTAVAIL => AddrNotAvailable, - c::WSAECONNABORTED => ConnectionAborted, - c::WSAECONNREFUSED => ConnectionRefused, - c::WSAECONNRESET => ConnectionReset, - c::WSAEINVAL => InvalidInput, - c::WSAENOTCONN => NotConnected, - c::WSAEWOULDBLOCK => WouldBlock, - c::WSAETIMEDOUT => TimedOut, - c::WSAEHOSTUNREACH => HostUnreachable, - c::WSAENETDOWN => NetworkDown, - c::WSAENETUNREACH => NetworkUnreachable, - c::WSAEDQUOT => QuotaExceeded, - - _ => Uncategorized, - } -} - pub fn unrolled_find_u16s(needle: u16, haystack: &[u16]) -> Option { let ptr = haystack.as_ptr(); let mut start = haystack; diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs index 1b3c80c079bef..3eb6ec8278401 100644 --- a/library/std/src/sys/pal/windows/os.rs +++ b/library/std/src/sys/pal/windows/os.rs @@ -15,66 +15,6 @@ use crate::path::{self, PathBuf}; use crate::sys::pal::{c, cvt}; use crate::{fmt, io, ptr}; -pub fn errno() -> i32 { - api::get_last_error().code as i32 -} - -/// Gets a detailed string description for the given error number. -pub fn error_string(mut errnum: i32) -> String { - let mut buf = [0 as c::WCHAR; 2048]; - - unsafe { - let mut module = ptr::null_mut(); - let mut flags = 0; - - // NTSTATUS errors may be encoded as HRESULT, which may returned from - // GetLastError. For more information about Windows error codes, see - // `[MS-ERREF]`: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/0642cb2f-2075-4469-918c-4441e69c548a - if (errnum & c::FACILITY_NT_BIT as i32) != 0 { - // format according to https://support.microsoft.com/en-us/help/259693 - const NTDLL_DLL: &[u16] = &[ - 'N' as _, 'T' as _, 'D' as _, 'L' as _, 'L' as _, '.' as _, 'D' as _, 'L' as _, - 'L' as _, 0, - ]; - module = c::GetModuleHandleW(NTDLL_DLL.as_ptr()); - - if !module.is_null() { - errnum ^= c::FACILITY_NT_BIT as i32; - flags = c::FORMAT_MESSAGE_FROM_HMODULE; - } - } - - let res = c::FormatMessageW( - flags | c::FORMAT_MESSAGE_FROM_SYSTEM | c::FORMAT_MESSAGE_IGNORE_INSERTS, - module, - errnum as u32, - 0, - buf.as_mut_ptr(), - buf.len() as u32, - ptr::null(), - ) as usize; - if res == 0 { - // Sometimes FormatMessageW can fail e.g., system doesn't like 0 as langId, - let fm_err = errno(); - return format!("OS Error {errnum} (FormatMessageW() returned error {fm_err})"); - } - - match String::from_utf16(&buf[..res]) { - Ok(mut msg) => { - // Trim trailing CRLF inserted by FormatMessageW - let len = msg.trim_end().len(); - msg.truncate(len); - msg - } - Err(..) => format!( - "OS Error {} (FormatMessageW() returned \ - invalid UTF-16)", - errnum - ), - } - } -} - pub struct SplitPaths<'a> { data: EncodeWide<'a>, must_yield: bool, diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs index 2da711f89dfaf..cd7b7b59d1127 100644 --- a/library/std/src/sys/pal/xous/os.rs +++ b/library/std/src/sys/pal/xous/os.rs @@ -1,7 +1,6 @@ use super::unsupported; use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; -use crate::os::xous::ffi::Error as XousError; use crate::path::{self, PathBuf}; use crate::sync::atomic::{Atomic, AtomicPtr, Ordering}; use crate::{fmt, io}; @@ -63,14 +62,6 @@ mod c_compat { } } -pub fn errno() -> i32 { - 0 -} - -pub fn error_string(errno: i32) -> String { - Into::::into(errno).to_string() -} - pub fn getcwd() -> io::Result { unsupported() } diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 6dece1055a089..f09020820a031 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -33,14 +33,6 @@ pub fn unsupported_err() -> std_io::Error { std_io::Error::UNSUPPORTED_PLATFORM } -pub fn is_interrupted(_code: i32) -> bool { - false -} - -pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { - crate::io::ErrorKind::Uncategorized -} - pub fn abort_internal() -> ! { core::intrinsics::abort(); } diff --git a/library/std/src/sys/pal/zkvm/os.rs b/library/std/src/sys/pal/zkvm/os.rs index 13d2a2044f48a..cb925ef4348db 100644 --- a/library/std/src/sys/pal/zkvm/os.rs +++ b/library/std/src/sys/pal/zkvm/os.rs @@ -4,14 +4,6 @@ use crate::marker::PhantomData; use crate::path::{self, PathBuf}; use crate::{fmt, io}; -pub fn errno() -> i32 { - 0 -} - -pub fn error_string(_errno: i32) -> String { - "operation successful".to_string() -} - pub fn getcwd() -> io::Result { unsupported() } diff --git a/library/std/src/sys/process/uefi.rs b/library/std/src/sys/process/uefi.rs index d627a477dc1ab..31914aeb67c59 100644 --- a/library/std/src/sys/process/uefi.rs +++ b/library/std/src/sys/process/uefi.rs @@ -8,8 +8,8 @@ use crate::num::{NonZero, NonZeroI32}; use crate::path::Path; use crate::process::StdioPipes; use crate::sys::fs::File; +use crate::sys::io::error_string; use crate::sys::pal::helpers; -use crate::sys::pal::os::error_string; use crate::sys::unsupported; use crate::{fmt, io}; diff --git a/library/std/src/sys/process/unix/common.rs b/library/std/src/sys/process/unix/common.rs index 2e1cd7068d7f9..f6bbfed61ef31 100644 --- a/library/std/src/sys/process/unix/common.rs +++ b/library/std/src/sys/process/unix/common.rs @@ -61,7 +61,7 @@ cfg_select! { let bit = (signum - 1) as usize; if set.is_null() || bit >= (8 * size_of::()) { - crate::sys::pal::os::set_errno(libc::EINVAL); + crate::sys::io::set_errno(libc::EINVAL); return -1; } let raw = slice::from_raw_parts_mut( diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs index 5ba57e11679cf..53fe69805de31 100644 --- a/library/std/src/sys/process/unix/unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -194,7 +194,7 @@ impl Command { // See also https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html #[cfg(target_os = "nto")] unsafe fn do_fork(&mut self) -> Result { - use crate::sys::os::errno; + use crate::sys::io::errno; let mut delay = MIN_FORKSPAWN_SLEEP; diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs index 53e2f1da67537..a5b790a1db42c 100644 --- a/library/std/src/sys/random/linux.rs +++ b/library/std/src/sys/random/linux.rs @@ -66,7 +66,7 @@ use crate::os::fd::AsRawFd; use crate::sync::OnceLock; use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; use crate::sync::atomic::{Atomic, AtomicBool}; -use crate::sys::pal::os::errno; +use crate::sys::io::errno; use crate::sys::pal::weak::syscall; fn getrandom(mut bytes: &mut [u8], insecure: bool) { diff --git a/library/std/src/sys/sync/condvar/windows7.rs b/library/std/src/sys/sync/condvar/windows7.rs index f03feef222124..c3f680be4bb5a 100644 --- a/library/std/src/sys/sync/condvar/windows7.rs +++ b/library/std/src/sys/sync/condvar/windows7.rs @@ -1,6 +1,6 @@ use crate::cell::UnsafeCell; +use crate::sys::c; use crate::sys::sync::{Mutex, mutex}; -use crate::sys::{c, os}; use crate::time::Duration; pub struct Condvar { @@ -30,7 +30,7 @@ impl Condvar { 0, ); if r == 0 { - debug_assert_eq!(os::errno() as usize, c::ERROR_TIMEOUT as usize); + debug_assert_eq!(crate::sys::io::errno() as usize, c::ERROR_TIMEOUT as usize); false } else { true diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index d0396ed713009..82e2e0456e649 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -14,10 +14,9 @@ use crate::num::NonZero; use crate::sys::weak::dlsym; #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto",))] use crate::sys::weak::weak; -use crate::sys::{os, stack_overflow}; use crate::thread::ThreadInit; use crate::time::Duration; -use crate::{cmp, io, ptr}; +use crate::{cmp, io, ptr, sys}; #[cfg(not(any( target_os = "l4re", target_os = "vxworks", @@ -77,7 +76,7 @@ impl Thread { // multiple of the system page size. Because it's definitely // >= PTHREAD_STACK_MIN, it must be an alignment issue. // Round up to the nearest page and try again. - let page_size = os::page_size(); + let page_size = sys::os::page_size(); let stack_size = (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1); @@ -114,7 +113,7 @@ impl Thread { // Now that the thread information is set, set up our stack // overflow handler. - let _handler = stack_overflow::Handler::new(); + let _handler = sys::stack_overflow::Handler::new(); rust_start(); } @@ -536,7 +535,7 @@ pub fn sleep(dur: Duration) { secs -= ts.tv_sec as u64; let ts_ptr = &raw mut ts; if libc::nanosleep(ts_ptr, ts_ptr) == -1 { - assert_eq!(os::errno(), libc::EINTR); + assert_eq!(sys::io::errno(), libc::EINTR); secs += ts.tv_sec as u64; nsecs = ts.tv_nsec; } else { From 0f25fca1a1f36ae93c76333a11132d8f54350b7c Mon Sep 17 00:00:00 2001 From: joboet Date: Tue, 6 Jan 2026 13:38:57 +0100 Subject: [PATCH 17/27] update import in UI test --- tests/ui/stability-attribute/stability-in-private-module.rs | 2 +- tests/ui/stability-attribute/stability-in-private-module.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/stability-attribute/stability-in-private-module.rs b/tests/ui/stability-attribute/stability-in-private-module.rs index df94931690b7c..000de46ab45e3 100644 --- a/tests/ui/stability-attribute/stability-in-private-module.rs +++ b/tests/ui/stability-attribute/stability-in-private-module.rs @@ -1,4 +1,4 @@ fn main() { - let _ = std::sys::os::errno(); + let _ = std::sys::io::errno(); //~^ERROR module `sys` is private } diff --git a/tests/ui/stability-attribute/stability-in-private-module.stderr b/tests/ui/stability-attribute/stability-in-private-module.stderr index e65f8aa9b1fc1..ab27f703ab6bd 100644 --- a/tests/ui/stability-attribute/stability-in-private-module.stderr +++ b/tests/ui/stability-attribute/stability-in-private-module.stderr @@ -1,7 +1,7 @@ error[E0603]: module `sys` is private --> $DIR/stability-in-private-module.rs:2:18 | -LL | let _ = std::sys::os::errno(); +LL | let _ = std::sys::io::errno(); | ^^^ ----- function `errno` is not publicly re-exported | | | private module From d1c2e5cf7bcfb402f8dbbaa2c651cfcb3a73b222 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Tue, 13 Jan 2026 20:53:48 +0800 Subject: [PATCH 18/27] Add test for issue 151048 --- .../mgca/tuple_expr_arg_bad-issue-151048.rs | 8 ++++++++ .../mgca/tuple_expr_arg_bad-issue-151048.stderr | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs create mode 100644 tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr 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 new file mode 100644 index 0000000000000..4aecd30e86bbb --- /dev/null +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs @@ -0,0 +1,8 @@ +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +struct Y { + stuff: [u8; { ([1, 2], 3, [4, 5]) }], //~ ERROR expected `usize`, found const tuple +} + +fn main() {} diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr new file mode 100644 index 0000000000000..468bf703d90d4 --- /dev/null +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr @@ -0,0 +1,8 @@ +error: expected `usize`, found const tuple + --> $DIR/tuple_expr_arg_bad-issue-151048.rs:5:19 + | +LL | stuff: [u8; { ([1, 2], 3, [4, 5]) }], + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From 8afa95d28f70a98d5b32b78f03a918ff5578e263 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 13 Jan 2026 15:16:06 +0000 Subject: [PATCH 19/27] Avoid should-fail in two ui tests should-fail is only meant for testing the compiletest framework itself. It checks that the test runner itself panicked. --- tests/ui/borrowck/two-phase-reservation-sharing-interference.rs | 2 +- tests/ui/type-inference/box_has_sigdrop.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs index 61446577db29b..342b8cce7b01d 100644 --- a/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs +++ b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs @@ -3,7 +3,7 @@ // The nll_beyond revision is disabled due to missing support from two-phase beyond autorefs //@ unused-revision-names: nll_beyond //@[nll_beyond]compile-flags: -Z two-phase-beyond-autoref -//@[nll_beyond]should-fail +//@[nll_beyond]check-fail // This is a corner case that the current implementation is (probably) // treating more conservatively than is necessary. But it also does diff --git a/tests/ui/type-inference/box_has_sigdrop.rs b/tests/ui/type-inference/box_has_sigdrop.rs index 3e801197a78e6..2d1b1cd0249e4 100644 --- a/tests/ui/type-inference/box_has_sigdrop.rs +++ b/tests/ui/type-inference/box_has_sigdrop.rs @@ -1,4 +1,4 @@ -//@ should-fail +//@ known-bug: unknown //@ compile-flags: -Wrust-2021-incompatible-closure-captures // Inference, canonicalization, and significant drops should work nicely together. // Related issue: #86868 From 15112eee6764c08f83d8c444dce7440d68adf9da Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 13 Jan 2026 15:21:20 +0000 Subject: [PATCH 20/27] Avoid should-fail in a codegen-llvm test --- .../codegen-llvm/option-niche-unfixed/option-nonzero-eq.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/codegen-llvm/option-niche-unfixed/option-nonzero-eq.rs b/tests/codegen-llvm/option-niche-unfixed/option-nonzero-eq.rs index 308856cfb7e9d..1eb4542323c1b 100644 --- a/tests/codegen-llvm/option-niche-unfixed/option-nonzero-eq.rs +++ b/tests/codegen-llvm/option-niche-unfixed/option-nonzero-eq.rs @@ -1,6 +1,5 @@ -//@ should-fail +//@ known-bug: #49892 //@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled -//! FIXME(#49892) //! Test that the derived implementation of `PartialEq` for `Option` is not fully //! optimized by LLVM. If this starts passing, the test and manual impl should //! be removed. @@ -18,7 +17,7 @@ pub enum Option { #[no_mangle] pub fn non_zero_eq(l: Option>, r: Option>) -> bool { // CHECK: start: - // CHECK-NEXT: icmp eq i32 - // CHECK-NEXT: ret i1 + // COMMENTEDCHECK-NEXT: icmp eq i32 + // COMMENTEDCHECK-NEXT: ret i1 l == r } From 27e09ce0be5693cd4767576bf97098ddb994d59e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 13 Jan 2026 16:53:21 +0000 Subject: [PATCH 21/27] Update ui-fulldeps --stage 2 tests --- tests/ui-fulldeps/rustc-dev-remap.only-remap.stderr | 2 +- tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr | 2 +- .../diagnostic-derive-doc-comment-field.stderr | 4 ++-- tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/ui-fulldeps/rustc-dev-remap.only-remap.stderr b/tests/ui-fulldeps/rustc-dev-remap.only-remap.stderr index d2303ef4bbb56..4a6ca56bf3293 100644 --- a/tests/ui-fulldeps/rustc-dev-remap.only-remap.stderr +++ b/tests/ui-fulldeps/rustc-dev-remap.only-remap.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `NotAValidResultType: VisitorResult` is not satisf LL | type Result = NotAValidResultType; | ^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound | -help: the trait `VisitorResult` is not implemented for `NotAValidResultType` +help: the nightly-only, unstable trait `VisitorResult` is not implemented for `NotAValidResultType` --> $DIR/rustc-dev-remap.rs:LL:COL | LL | struct NotAValidResultType; diff --git a/tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr b/tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr index 50bb60e78d680..18dffdb2cf795 100644 --- a/tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr +++ b/tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `NotAValidResultType: VisitorResult` is not satisf LL | type Result = NotAValidResultType; | ^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound | -help: the trait `VisitorResult` is not implemented for `NotAValidResultType` +help: the nightly-only, unstable trait `VisitorResult` is not implemented for `NotAValidResultType` --> $DIR/rustc-dev-remap.rs:LL:COL | LL | struct NotAValidResultType; 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 72e150dd5178d..316f23888bc1f 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 @@ -7,7 +7,7 @@ LL | #[derive(Diagnostic)] LL | arg: NotIntoDiagArg, | ^^^^^^^^^^^^^^ unsatisfied trait bound | -help: the trait `IntoDiagArg` is not implemented for `NotIntoDiagArg` +help: the nightly-only, unstable trait `IntoDiagArg` is not implemented for `NotIntoDiagArg` --> $DIR/diagnostic-derive-doc-comment-field.rs:28:1 | LL | struct NotIntoDiagArg; @@ -29,7 +29,7 @@ LL | #[derive(Subdiagnostic)] LL | arg: NotIntoDiagArg, | ^^^^^^^^^^^^^^ unsatisfied trait bound | -help: the trait `IntoDiagArg` is not implemented for `NotIntoDiagArg` +help: the nightly-only, unstable trait `IntoDiagArg` is not implemented for `NotIntoDiagArg` --> $DIR/diagnostic-derive-doc-comment-field.rs:28:1 | LL | struct NotIntoDiagArg; diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index f2244a9687698..90ad21ef08f94 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -657,7 +657,7 @@ LL | #[derive(Diagnostic)] LL | other: Hello, | ^^^^^ unsatisfied trait bound | -help: the trait `IntoDiagArg` is not implemented for `Hello` +help: the nightly-only, unstable trait `IntoDiagArg` is not implemented for `Hello` --> $DIR/diagnostic-derive.rs:40:1 | LL | struct Hello {} From 814647f047e277399b6185b9e94f6096edb16a07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 26 Dec 2025 20:23:50 +0000 Subject: [PATCH 22/27] Change some `matches!(.., .. if ..)` with let-chains --- compiler/rustc_const_eval/src/check_consts/check.rs | 13 +++++++------ .../rustc_lint/src/early/diagnostics/check_cfg.rs | 2 +- compiler/rustc_lint/src/transmute.rs | 4 +++- compiler/rustc_middle/src/mir/pretty.rs | 7 +++++-- compiler/rustc_parse/src/parser/diagnostics.rs | 4 +++- compiler/rustc_parse/src/parser/mod.rs | 7 +++---- .../src/error_reporting/traits/suggestions.rs | 3 ++- 7 files changed, 24 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index b06b407a6085a..3a85ca3760d20 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -833,12 +833,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // const-eval of `panic_display` assumes the argument is `&&str` if tcx.is_lang_item(callee, LangItem::PanicDisplay) { - match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() { - ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) => - {} - _ => { - self.check_op(ops::PanicNonStr); - } + if let ty::Ref(_, ty, _) = + args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() + && let ty::Ref(_, ty, _) = ty.kind() + && ty.is_str() + { + } else { + self.check_op(ops::PanicNonStr); } // Allow this call, skip all the checks below. return; diff --git a/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs index 0c8d7523a9dc5..fab0e9e863dc5 100644 --- a/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs @@ -70,7 +70,7 @@ fn cargo_help_sub( // `build_script_build`) to try to figure out if we are building a Cargo build script let unescaped = &inst(EscapeQuotes::No); - if matches!(&sess.opts.crate_name, Some(crate_name) if crate_name == "build_script_build") { + if let Some("build_script_build") = sess.opts.crate_name.as_deref() { lints::UnexpectedCfgCargoHelp::lint_cfg(unescaped) } else { lints::UnexpectedCfgCargoHelp::lint_cfg_and_build_rs(unescaped, &inst(EscapeQuotes::Yes)) diff --git a/compiler/rustc_lint/src/transmute.rs b/compiler/rustc_lint/src/transmute.rs index 98510eea73b8f..6bc4617eb2dcf 100644 --- a/compiler/rustc_lint/src/transmute.rs +++ b/compiler/rustc_lint/src/transmute.rs @@ -152,7 +152,9 @@ fn check_int_to_ptr_transmute<'tcx>( return; }; // bail-out if the argument is literal 0 as we have other lints for those cases - if matches!(arg.kind, hir::ExprKind::Lit(hir::Lit { node: LitKind::Int(v, _), .. }) if v == 0) { + if let hir::ExprKind::Lit(hir::Lit { node: LitKind::Int(v, _), .. }) = arg.kind + && v == 0 + { return; } // bail-out if the inner type is a ZST diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index a31f03362a3d3..ded02595563c9 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1871,13 +1871,16 @@ fn pretty_print_const_value_tcx<'tcx>( let u8_type = tcx.types.u8; match (ct, ty.kind()) { // Byte/string slices, printed as (byte) string literals. - (_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => { + (_, ty::Ref(_, inner_ty, _)) if let ty::Str = inner_ty.kind() => { if let Some(data) = ct.try_get_slice_bytes_for_diagnostics(tcx) { fmt.write_str(&format!("{:?}", String::from_utf8_lossy(data)))?; return Ok(()); } } - (_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Slice(t) if *t == u8_type) => { + (_, ty::Ref(_, inner_ty, _)) + if let ty::Slice(t) = inner_ty.kind() + && *t == u8_type => + { if let Some(data) = ct.try_get_slice_bytes_for_diagnostics(tcx) { pretty_print_byte_str(fmt, data)?; return Ok(()); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 70ec80a508126..2fd1d146b1f61 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -761,7 +761,9 @@ impl<'a> Parser<'a> { } // Check for misspelled keywords if there are no suggestions added to the diagnostic. - if matches!(&err.suggestions, Suggestions::Enabled(list) if list.is_empty()) { + if let Suggestions::Enabled(list) = &err.suggestions + && list.is_empty() + { self.check_for_misspelled_kw(&mut err, &expected); } Err(err) diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 4dade1d012828..d6e99bc540f74 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1203,10 +1203,9 @@ impl<'a> Parser<'a> { let mut token = Token::dummy(); while i < dist { token = cursor.next().0; - if matches!( - token.kind, - token::OpenInvisible(origin) | token::CloseInvisible(origin) if origin.skip() - ) { + if let token::OpenInvisible(origin) | token::CloseInvisible(origin) = token.kind + && origin.skip() + { continue; } i += 1; 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 511e9e85b5f60..507371425e4f6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4722,7 +4722,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // slices of `element_ty` with `mutability`. let mut is_slice = |candidate: Ty<'tcx>| match *candidate.kind() { ty::RawPtr(t, m) | ty::Ref(_, t, m) => { - if matches!(*t.kind(), ty::Slice(e) if e == element_ty) + if let ty::Slice(e) = *t.kind() + && e == element_ty && m == mutability.unwrap_or(m) { // Use the candidate's mutability going forward. From c4820e6cb45407c8d34ebf7fe7a8bdd683f2003f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 9 Jan 2026 14:40:20 +0300 Subject: [PATCH 23/27] resolve: Refactor away the side table `decl_parent_modules` Instead keep parent modules in `DeclData` itself --- .../rustc_resolve/src/build_reduced_graph.rs | 33 ++++++++++--------- compiler/rustc_resolve/src/diagnostics.rs | 27 +++++++-------- compiler/rustc_resolve/src/imports.rs | 9 ++--- compiler/rustc_resolve/src/lib.rs | 31 +++++++---------- 4 files changed, 46 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 752d8c46beb48..736648c125b69 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -48,14 +48,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// and report an error in case of a collision. pub(crate) fn plant_decl_into_local_module( &mut self, - parent: Module<'ra>, ident: Macros20NormalizedIdent, ns: Namespace, decl: Decl<'ra>, ) { - if let Err(old_decl) = self.try_plant_decl_into_local_module(parent, ident, ns, decl, false) - { - self.report_conflict(parent, ident.0, ns, old_decl, decl); + if let Err(old_decl) = self.try_plant_decl_into_local_module(ident, ns, decl, false) { + self.report_conflict(ident.0, ns, old_decl, decl); } } @@ -70,9 +68,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span: Span, expn_id: LocalExpnId, ) { - let decl = self.arenas.new_def_decl(res, vis.to_def_id(), span, expn_id); + let decl = self.arenas.new_def_decl(res, vis.to_def_id(), span, expn_id, Some(parent)); let ident = Macros20NormalizedIdent::new(ident); - self.plant_decl_into_local_module(parent, ident, ns, decl); + self.plant_decl_into_local_module(ident, ns, decl); } /// Create a name definitinon from the given components, and put it into the extern module. @@ -96,6 +94,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { vis: CmCell::new(vis), span, expansion, + parent_module: Some(parent), }); // Even if underscore names cannot be looked up, we still need to add them to modules, // because they can be fetched by glob imports from those modules, and bring traits @@ -289,7 +288,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let ModChild { ident: _, res, vis, ref reexport_chain } = *ambig_child; let span = child_span(self, reexport_chain, res); let res = res.expect_non_local(); - self.arenas.new_def_decl(res, vis, span, expansion) + self.arenas.new_def_decl(res, vis, span, expansion, Some(parent)) }); // Record primary definitions. @@ -844,7 +843,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ident, local_def_id, vis, - parent, ); } @@ -976,10 +974,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ident: Ident, local_def_id: LocalDefId, vis: Visibility, - parent: Module<'ra>, ) { let sp = item.span; let parent_scope = self.parent_scope; + let parent = parent_scope.module; let expansion = parent_scope.expansion; let (used, module, decl) = if orig_name.is_none() && ident.name == kw::SelfLower { @@ -1009,7 +1007,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let import = self.r.arenas.alloc_import(ImportData { kind: ImportKind::ExternCrate { source: orig_name, target: ident, id: item.id }, root_id: item.id, - parent_scope: self.parent_scope, + parent_scope, imported_module: CmCell::new(module), has_attributes: !item.attrs.is_empty(), use_span_with_attributes: item.span_with_attributes(), @@ -1057,7 +1055,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { }), }; } - self.r.plant_decl_into_local_module(parent, ident, TypeNS, import_decl); + self.r.plant_decl_into_local_module(ident, TypeNS, import_decl); } /// Constructs the reduced graph for one foreign item. @@ -1300,14 +1298,19 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } else { Visibility::Restricted(CRATE_DEF_ID) }; - let decl = self.r.arenas.new_def_decl(res, vis.to_def_id(), span, expansion); - self.r.set_decl_parent_module(decl, parent_scope.module); + let decl = self.r.arenas.new_def_decl( + res, + vis.to_def_id(), + span, + expansion, + Some(parent_scope.module), + ); self.r.all_macro_rules.insert(ident.name); if is_macro_export { let import = self.r.arenas.alloc_import(ImportData { kind: ImportKind::MacroExport, root_id: item.id, - parent_scope: self.parent_scope, + parent_scope: ParentScope { module: self.r.graph_root, ..parent_scope }, imported_module: CmCell::new(None), has_attributes: false, use_span_with_attributes: span, @@ -1320,7 +1323,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { }); self.r.import_use_map.insert(import, Used::Other); let import_decl = self.r.new_import_decl(decl, import); - self.r.plant_decl_into_local_module(self.r.graph_root, ident, MacroNS, import_decl); + self.r.plant_decl_into_local_module(ident, MacroNS, import_decl); } else { self.r.check_reserved_macro_name(ident.0, res); self.insert_unused_macro(ident.0, def_id, item.id); diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7bc08f1de5462..b80011e8c0cb7 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -210,7 +210,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn report_conflict( &mut self, - parent: Module<'_>, ident: Ident, ns: Namespace, new_binding: Decl<'ra>, @@ -218,13 +217,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) { // Error on the second of two conflicting names if old_binding.span.lo() > new_binding.span.lo() { - return self.report_conflict(parent, ident, ns, old_binding, new_binding); + return self.report_conflict(ident, ns, old_binding, new_binding); } - let container = match parent.kind { + let container = match old_binding.parent_module.unwrap().kind { // Avoid using TyCtxt::def_kind_descr in the resolver, because it // indirectly *calls* the resolver, and would cause a query cycle. - ModuleKind::Def(kind, _, _) => kind.descr(parent.def_id()), + ModuleKind::Def(kind, def_id, _) => kind.descr(def_id), ModuleKind::Block => "block", }; @@ -2034,15 +2033,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously")) } - if let Scope::ModuleNonGlobs(module, _) | Scope::ModuleGlobs(module, _) = scope { - if module == self.graph_root { - help_msgs.push(format!( - "use `crate::{ident}` to refer to this {thing} unambiguously" - )); - } else if module != self.empty_module && module.is_normal() { - help_msgs.push(format!( - "use `self::{ident}` to refer to this {thing} unambiguously" - )); + if kind != AmbiguityKind::GlobVsGlob { + if let Scope::ModuleNonGlobs(module, _) | Scope::ModuleGlobs(module, _) = scope { + if module == self.graph_root { + help_msgs.push(format!( + "use `crate::{ident}` to refer to this {thing} unambiguously" + )); + } else if module.is_normal() { + help_msgs.push(format!( + "use `self::{ident}` to refer to this {thing} unambiguously" + )); + } } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 4447374b8b06c..e525abd00f998 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -340,6 +340,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span: import.span, vis: CmCell::new(vis), expansion: import.parent_scope.expansion, + parent_module: Some(import.parent_scope.module), }) } @@ -409,15 +410,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// and return existing declaration if there is a collision. pub(crate) fn try_plant_decl_into_local_module( &mut self, - module: Module<'ra>, ident: Macros20NormalizedIdent, ns: Namespace, decl: Decl<'ra>, warn_ambiguity: bool, ) -> Result<(), Decl<'ra>> { + let module = decl.parent_module.unwrap(); let res = decl.res(); self.check_reserved_macro_name(ident.0, res); - self.set_decl_parent_module(decl, module); // Even if underscore names cannot be looked up, we still need to add them to modules, // because they can be fetched by glob imports from those modules, and bring traits // into scope both directly and through glob imports. @@ -511,7 +511,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if self.is_accessible_from(binding.vis(), scope) { let import_decl = self.new_import_decl(binding, *import); let _ = self.try_plant_decl_into_local_module( - import.parent_scope.module, ident, key.ns, import_decl, @@ -535,7 +534,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.per_ns(|this, ns| { let module = import.parent_scope.module; let ident = Macros20NormalizedIdent::new(target); - let _ = this.try_plant_decl_into_local_module(module, ident, ns, dummy_decl, false); + let _ = this.try_plant_decl_into_local_module(ident, ns, dummy_decl, false); // Don't remove underscores from `single_imports`, they were never added. if target.name != kw::Underscore { let key = BindingKey::new(ident, ns); @@ -916,7 +915,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // We need the `target`, `source` can be extracted. let import_decl = this.new_import_decl(binding, import); this.get_mut_unchecked().plant_decl_into_local_module( - parent, Macros20NormalizedIdent::new(target), ns, import_decl, @@ -1542,7 +1540,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .and_then(|r| r.binding()) .is_some_and(|binding| binding.warn_ambiguity_recursive()); let _ = self.try_plant_decl_into_local_module( - import.parent_scope.module, key.ident, key.ns, import_decl, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index c4c1e06f94ae2..2c22aacb32412 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -67,7 +67,6 @@ use rustc_metadata::creader::CStore; use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport}; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::query::Providers; -use rustc_middle::span_bug; use rustc_middle::ty::{ self, DelegationFnSig, DelegationInfo, Feed, MainDefinition, RegisteredTools, ResolverAstLowering, ResolverGlobalCtxt, TyCtxt, TyCtxtFeed, Visibility, @@ -812,6 +811,7 @@ struct DeclData<'ra> { expansion: LocalExpnId, span: Span, vis: CmCell>, + parent_module: Option>, } /// All name declarations are unique and allocated on a same arena, @@ -922,7 +922,6 @@ struct AmbiguityError<'ra> { ident: Ident, b1: Decl<'ra>, b2: Decl<'ra>, - // `empty_module` in module scope serves as an unknown module here. scope1: Scope<'ra>, scope2: Scope<'ra>, warning: Option, @@ -1186,7 +1185,6 @@ pub struct Resolver<'ra, 'tcx> { local_module_map: FxIndexMap>, /// Lazily populated cache of modules loaded from external crates. extern_module_map: CacheRefCell>>, - decl_parent_modules: FxHashMap, Module<'ra>>, /// Maps glob imports to the names of items actually imported. glob_map: FxIndexMap>, @@ -1349,6 +1347,7 @@ impl<'ra> ResolverArenas<'ra> { vis: Visibility, span: Span, expansion: LocalExpnId, + parent_module: Option>, ) -> Decl<'ra> { self.alloc_decl(DeclData { kind: DeclKind::Def(res), @@ -1357,11 +1356,12 @@ impl<'ra> ResolverArenas<'ra> { vis: CmCell::new(vis), span, expansion, + parent_module, }) } fn new_pub_def_decl(&'ra self, res: Res, span: Span, expn_id: LocalExpnId) -> Decl<'ra> { - self.new_def_decl(res, Visibility::Public, span, expn_id) + self.new_def_decl(res, Visibility::Public, span, expn_id, None) } fn new_module( @@ -1616,7 +1616,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { local_module_map, extern_module_map: Default::default(), block_map: Default::default(), - decl_parent_modules: FxHashMap::default(), ast_transform_scopes: FxHashMap::default(), glob_map: Default::default(), @@ -2071,8 +2070,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident, b1: used_decl, b2, - scope1: Scope::ModuleGlobs(self.empty_module, None), - scope2: Scope::ModuleGlobs(self.empty_module, None), + scope1: Scope::ModuleGlobs(used_decl.parent_module.unwrap(), None), + scope2: Scope::ModuleGlobs(b2.parent_module.unwrap(), None), warning: if warn_ambiguity { Some(AmbiguityWarning::GlobImport) } else { None }, }; if !self.matches_previous_ambiguity_error(&ambiguity_error) { @@ -2237,14 +2236,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { vis.is_accessible_from(module.nearest_parent_mod(), self.tcx) } - fn set_decl_parent_module(&mut self, decl: Decl<'ra>, module: Module<'ra>) { - if let Some(old_module) = self.decl_parent_modules.insert(decl, module) { - if module != old_module { - span_bug!(decl.span, "parent module is reset for a name declaration"); - } - } - } - fn disambiguate_macro_rules_vs_modularized( &self, macro_rules: Decl<'ra>, @@ -2254,13 +2245,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // is disambiguated to mitigate regressions from macro modularization. // Scoping for `macro_rules` behaves like scoping for `let` at module level, in general. // - // panic on index should be impossible, the only name_bindings passed in should be from + // Panic on unwrap should be impossible, the only name_bindings passed in should be from // `resolve_ident_in_scope_set` which will always refer to a local binding from an - // import or macro definition - let macro_rules = &self.decl_parent_modules[¯o_rules]; - let modularized = &self.decl_parent_modules[&modularized]; + // import or macro definition. + let macro_rules = macro_rules.parent_module.unwrap(); + let modularized = modularized.parent_module.unwrap(); macro_rules.nearest_parent_mod() == modularized.nearest_parent_mod() - && modularized.is_ancestor_of(*macro_rules) + && modularized.is_ancestor_of(macro_rules) } fn extern_prelude_get_item<'r>( From 5435e8188ce1bf0912b3a98a54e316e391d3ca27 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Tue, 13 Jan 2026 18:52:04 +0100 Subject: [PATCH 24/27] also handle ENOTTY ioctl errors when checking pidfd -> pid support Otherwise the std testsuite fails on older kernels. --- library/std/src/sys/pal/unix/linux/pidfd.rs | 2 +- library/std/src/sys/pal/unix/linux/pidfd/tests.rs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/unix/linux/pidfd.rs b/library/std/src/sys/pal/unix/linux/pidfd.rs index e9e4831fcc02b..671046949aa16 100644 --- a/library/std/src/sys/pal/unix/linux/pidfd.rs +++ b/library/std/src/sys/pal/unix/linux/pidfd.rs @@ -33,7 +33,7 @@ impl PidFd { match cvt(unsafe { libc::ioctl(self.0.as_raw_fd(), libc::PIDFD_GET_INFO, &mut pidfd_info) }) { Ok(_) => {} - Err(e) if e.raw_os_error() == Some(libc::EINVAL) => { + Err(e) if matches!(e.raw_os_error(), Some(libc::EINVAL | libc::ENOTTY)) => { // kernel doesn't support that ioctl, try the glibc helper that looks at procfs weak!( fn pidfd_getpid(pidfd: RawFd) -> libc::pid_t; diff --git a/library/std/src/sys/pal/unix/linux/pidfd/tests.rs b/library/std/src/sys/pal/unix/linux/pidfd/tests.rs index a3bb5d5d64ba5..0330f28e647d3 100644 --- a/library/std/src/sys/pal/unix/linux/pidfd/tests.rs +++ b/library/std/src/sys/pal/unix/linux/pidfd/tests.rs @@ -1,6 +1,5 @@ use super::PidFd as InternalPidFd; use crate::assert_matches::assert_matches; -use crate::io::ErrorKind; use crate::os::fd::AsRawFd; use crate::os::linux::process::{ChildExt, CommandExt as _}; use crate::os::unix::process::{CommandExt as _, ExitStatusExt}; @@ -62,7 +61,9 @@ fn test_command_pidfd() { if let Ok(pidfd) = child.pidfd() { match pidfd.as_inner().pid() { Ok(pid) => assert_eq!(pid, id), - Err(e) if e.kind() == ErrorKind::InvalidInput => { /* older kernel */ } + Err(e) if matches!(e.raw_os_error(), Some(libc::EINVAL | libc::ENOTTY)) => { + /* older kernel */ + } Err(e) => panic!("unexpected error getting pid from pidfd: {}", e), } } From 1fe705ca709cd81d3ce8735e992cd4333c1404fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 13 Jan 2026 16:59:03 +0000 Subject: [PATCH 25/27] Mention the type in the label, to avoid confusion at the cost of redundancy --- library/core/src/iter/range.rs | 2 +- .../run-make/missing-unstable-trait-bound/missing-bound.stderr | 2 +- tests/ui/range/range-1.stderr | 2 +- tests/ui/trait-bounds/unstable-trait-suggestion.stderr | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 7880e18d7d318..a6ab2e4d8b7d8 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -23,7 +23,7 @@ unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u6 #[rustc_diagnostic_item = "range_step"] #[rustc_on_unimplemented( message = "`std::ops::Range<{Self}>` is not an iterator", - label = "not an iterator", + label = "`Range<{Self}>` is not an iterator", note = "`Range` only implements `Iterator` for select types in the standard library, \ particularly integers; to see the full list of types, see the documentation for the \ unstable `Step` trait" diff --git a/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr b/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr index d503751a2e933..d680ae1aca1d3 100644 --- a/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr +++ b/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr @@ -2,7 +2,7 @@ error[E0277]: `std::ops::Range` is not an iterator --> missing-bound.rs:2:14 | 2 | for _ in t {} - | ^ not an iterator + | ^ `Range` is not an iterator | = note: `Range` only implements `Iterator` for select types in the standard library, particularly integers; to see the full list of types, see the documentation for the unstable `Step` trait = note: required for `std::ops::Range` to implement `Iterator` diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr index 9682122539c56..d7d0f87ac991d 100644 --- a/tests/ui/range/range-1.stderr +++ b/tests/ui/range/range-1.stderr @@ -8,7 +8,7 @@ error[E0277]: `std::ops::Range` is not an iterator --> $DIR/range-1.rs:9:14 | LL | for i in false..true {} - | ^^^^^^^^^^^ not an iterator + | ^^^^^^^^^^^ `Range` is not an iterator | = help: the nightly-only, unstable trait `Step` is not implemented for `bool` = note: `Range` only implements `Iterator` for select types in the standard library, particularly integers; to see the full list of types, see the documentation for the unstable `Step` trait diff --git a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr index 5edaed0f4dfea..9ae209d5aa961 100644 --- a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr +++ b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr @@ -20,7 +20,7 @@ error[E0277]: `std::ops::Range` is not an iterator --> $DIR/unstable-trait-suggestion.rs:17:14 | LL | for _ in t {} - | ^ not an iterator + | ^ `Range` is not an iterator | = note: `Range` only implements `Iterator` for select types in the standard library, particularly integers; to see the full list of types, see the documentation for the unstable `Step` trait = note: required for `std::ops::Range` to implement `Iterator` From 15d8e9ea66442a7ee8c642245aaa77f6a78f2cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 13 Jan 2026 19:33:40 +0000 Subject: [PATCH 26/27] Recognize potential `impl` to `impl` mistake When encountering code like `impl Bar for [u8; N]`, suggest `impl Bar for [u8; N]` as a possibility. ``` error[E0423]: expected value, found type parameter `T` --> $DIR/issue-69654.rs:5:25 | LL | impl Bar for [u8; T] {} | - ^ not a value | | | found this type parameter | help: you might have meant to write a const parameter here | LL | impl Bar for [u8; T] {} | +++++ ++++++++++++ ``` --- compiler/rustc_resolve/src/errors.rs | 13 +++++++ .../rustc_resolve/src/late/diagnostics.rs | 35 ++++++++++++++++++- .../generic_const_exprs/issue-69654.stderr | 5 +++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index af58d88ec35f2..8880c2ba26668 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -867,6 +867,19 @@ pub(crate) struct UnexpectedResChangeTyToConstParamSugg { pub applicability: Applicability, } +#[derive(Subdiagnostic)] +#[multipart_suggestion( + resolve_unexpected_res_change_ty_to_const_param_sugg, + applicability = "has-placeholders", + style = "verbose" +)] +pub(crate) struct UnexpectedResChangeTyParamToConstParamSugg { + #[suggestion_part(code = "const ")] + pub before: Span, + #[suggestion_part(code = ": /* Type */")] + pub after: Span, +} + #[derive(Subdiagnostic)] #[suggestion( resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a2805497e7961..c5d15dcc91af9 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -414,6 +414,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { /// Handles error reporting for `smart_resolve_path_fragment` function. /// Creates base error and amends it with one short label and possibly some longer helps/notes. + #[tracing::instrument(skip(self), level = "debug")] pub(crate) fn smart_resolve_report_errors( &mut self, path: &[Segment], @@ -451,7 +452,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err.span_suggestion_verbose(sugg.0, sugg.1, &sugg.2, Applicability::MaybeIncorrect); } - self.suggest_changing_type_to_const_param(&mut err, res, source, span); + self.suggest_changing_type_to_const_param(&mut err, res, source, path, following_seg, span); self.explain_functions_in_pattern(&mut err, res, source); if self.suggest_pattern_match_with_let(&mut err, source, span) { @@ -1505,8 +1506,40 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err: &mut Diag<'_>, res: Option, source: PathSource<'_, '_, '_>, + path: &[Segment], + following_seg: Option<&Segment>, span: Span, ) { + if let PathSource::Expr(None) = source + && let Some(Res::Def(DefKind::TyParam, _)) = res + && following_seg.is_none() + && let [segment] = path + { + // We have something like + // impl From<[T; N]> for VecWrapper { + // fn from(slice: [T; N]) -> Self { + // VecWrapper(slice.to_vec()) + // } + // } + // where `N` is a type param but should likely have been a const param. + let Some(item) = self.diag_metadata.current_item else { return }; + let Some(generics) = item.kind.generics() else { return }; + let Some(span) = generics.params.iter().find_map(|param| { + // Only consider type params with no bounds. + if param.bounds.is_empty() && param.ident.name == segment.ident.name { + Some(param.ident.span) + } else { + None + } + }) else { + return; + }; + err.subdiagnostic(errors::UnexpectedResChangeTyParamToConstParamSugg { + before: span.shrink_to_lo(), + after: span.shrink_to_hi(), + }); + return; + } let PathSource::Trait(_) = source else { return }; // We don't include `DefKind::Str` and `DefKind::AssocTy` as they can't be reached here anyway. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr b/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr index eb4ff8305dac8..7fa0d8c7dbaa9 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr @@ -5,6 +5,11 @@ LL | impl Bar for [u8; T] {} | - ^ not a value | | | found this type parameter + | +help: you might have meant to write a const parameter here + | +LL | impl Bar for [u8; T] {} + | +++++ ++++++++++++ error[E0599]: the function or associated item `foo` exists for struct `Foo<_>`, but its trait bounds were not satisfied --> $DIR/issue-69654.rs:17:10 From 3aa31788b57da7a5eeee8184dccb00178b40121b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 14 Jan 2026 10:30:08 +1100 Subject: [PATCH 27/27] Remove `Deref`/`DerefMut` impl for `Providers`. It's described as a "backwards compatibility hack to keep the diff small". Removing it requires only a modest amount of churn, and the resulting code is clearer without the invisible derefs. --- compiler/rustc_codegen_gcc/src/lib.rs | 3 +- compiler/rustc_codegen_llvm/src/lib.rs | 2 +- .../src/back/symbol_export.rs | 18 ++++---- compiler/rustc_codegen_ssa/src/lib.rs | 6 +-- compiler/rustc_const_eval/src/lib.rs | 16 +++---- compiler/rustc_interface/src/passes.rs | 46 +++++++++---------- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/util/mod.rs | 17 ------- compiler/rustc_mir_build/src/lib.rs | 12 ++--- compiler/rustc_mir_transform/src/lib.rs | 6 +-- compiler/rustc_monomorphize/src/collector.rs | 2 +- compiler/rustc_monomorphize/src/lib.rs | 2 +- .../rustc_monomorphize/src/partitioning.rs | 8 ++-- compiler/rustc_passes/src/lib.rs | 2 +- src/librustdoc/core.rs | 9 ++-- src/tools/miri/src/bin/miri.rs | 2 +- tests/ui-fulldeps/obtain-borrowck.rs | 6 +-- 17 files changed, 72 insertions(+), 87 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 96d3a0024f418..cf1be18062355 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -286,7 +286,8 @@ impl CodegenBackend for GccCodegenBackend { } fn provide(&self, providers: &mut Providers) { - providers.global_backend_features = |tcx, ()| gcc_util::global_gcc_features(tcx.sess) + providers.queries.global_backend_features = + |tcx, ()| gcc_util::global_gcc_features(tcx.sess) } fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box { diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 438a74e0a0912..e0007f69828dc 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -264,7 +264,7 @@ impl CodegenBackend for LlvmCodegenBackend { } fn provide(&self, providers: &mut Providers) { - providers.global_backend_features = + providers.queries.global_backend_features = |tcx, ()| llvm_util::global_llvm_features(tcx.sess, false) } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 27989f6f5ea24..59d0f5ee9d54c 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -474,15 +474,15 @@ fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: LocalDefId) } pub(crate) fn provide(providers: &mut Providers) { - providers.reachable_non_generics = reachable_non_generics_provider; - providers.is_reachable_non_generic = is_reachable_non_generic_provider_local; - providers.exported_non_generic_symbols = exported_non_generic_symbols_provider_local; - providers.exported_generic_symbols = exported_generic_symbols_provider_local; - providers.upstream_monomorphizations = upstream_monomorphizations_provider; - providers.is_unreachable_local_definition = is_unreachable_local_definition_provider; - providers.upstream_drop_glue_for = upstream_drop_glue_for_provider; - providers.upstream_async_drop_glue_for = upstream_async_drop_glue_for_provider; - providers.wasm_import_module_map = wasm_import_module_map; + providers.queries.reachable_non_generics = reachable_non_generics_provider; + providers.queries.is_reachable_non_generic = is_reachable_non_generic_provider_local; + providers.queries.exported_non_generic_symbols = exported_non_generic_symbols_provider_local; + providers.queries.exported_generic_symbols = exported_generic_symbols_provider_local; + providers.queries.upstream_monomorphizations = upstream_monomorphizations_provider; + providers.queries.is_unreachable_local_definition = is_unreachable_local_definition_provider; + providers.queries.upstream_drop_glue_for = upstream_drop_glue_for_provider; + providers.queries.upstream_async_drop_glue_for = upstream_async_drop_glue_for_provider; + providers.queries.wasm_import_module_map = wasm_import_module_map; providers.extern_queries.is_reachable_non_generic = is_reachable_non_generic_provider_extern; providers.extern_queries.upstream_monomorphizations_for = upstream_monomorphizations_for_provider; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index d7461c76ff03e..8c39d04ef21dd 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -266,9 +266,9 @@ pub enum CodegenErrors { pub fn provide(providers: &mut Providers) { crate::back::symbol_export::provide(providers); - crate::base::provide(providers); - crate::target_features::provide(providers); - crate::codegen_attrs::provide(providers); + crate::base::provide(&mut providers.queries); + crate::target_features::provide(&mut providers.queries); + crate::codegen_attrs::provide(&mut providers.queries); providers.queries.global_backend_features = |_tcx: TyCtxt<'_>, ()| vec![]; } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 2fce4b8c0566e..9b1d4652212b6 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -30,20 +30,20 @@ pub use self::errors::ReportErrorExt; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn provide(providers: &mut Providers) { - const_eval::provide(providers); - providers.tag_for_variant = const_eval::tag_for_variant_provider; - providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider; - providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider; - providers.eval_static_initializer = const_eval::eval_static_initializer_provider; + const_eval::provide(&mut providers.queries); + providers.queries.tag_for_variant = const_eval::tag_for_variant_provider; + providers.queries.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider; + providers.queries.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider; + providers.queries.eval_static_initializer = const_eval::eval_static_initializer_provider; providers.hooks.const_caller_location = util::caller_location::const_caller_location_provider; - providers.eval_to_valtree = |tcx, ty::PseudoCanonicalInput { typing_env, value }| { + providers.queries.eval_to_valtree = |tcx, ty::PseudoCanonicalInput { typing_env, value }| { const_eval::eval_to_valtree(tcx, typing_env, value) }; providers.hooks.try_destructure_mir_constant_for_user_output = const_eval::try_destructure_mir_constant_for_user_output; - providers.valtree_to_const_val = + providers.queries.valtree_to_const_val = |tcx, cv| const_eval::valtree_to_const_value(tcx, ty::TypingEnv::fully_monomorphized(), cv); - providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| { + providers.queries.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| { util::check_validity_requirement(tcx, init_kind, param_env_and_ty) }; providers.hooks.validate_scalar_in_layout = diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index a0383b187de51..35ab202d4c27e 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -880,36 +880,36 @@ pub fn write_interface<'tcx>(tcx: TyCtxt<'tcx>) { pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { let providers = &mut Providers::default(); - providers.analysis = analysis; - providers.hir_crate = rustc_ast_lowering::lower_to_hir; - providers.resolver_for_lowering_raw = resolver_for_lowering_raw; - providers.stripped_cfg_items = |tcx, _| &tcx.resolutions(()).stripped_cfg_items[..]; - providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1; - providers.early_lint_checks = early_lint_checks; - providers.env_var_os = env_var_os; - limits::provide(providers); - proc_macro_decls::provide(providers); + providers.queries.analysis = analysis; + providers.queries.hir_crate = rustc_ast_lowering::lower_to_hir; + providers.queries.resolver_for_lowering_raw = resolver_for_lowering_raw; + providers.queries.stripped_cfg_items = |tcx, _| &tcx.resolutions(()).stripped_cfg_items[..]; + providers.queries.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1; + providers.queries.early_lint_checks = early_lint_checks; + providers.queries.env_var_os = env_var_os; + limits::provide(&mut providers.queries); + proc_macro_decls::provide(&mut providers.queries); rustc_const_eval::provide(providers); - rustc_middle::hir::provide(providers); - rustc_borrowck::provide(providers); + rustc_middle::hir::provide(&mut providers.queries); + rustc_borrowck::provide(&mut providers.queries); rustc_incremental::provide(providers); rustc_mir_build::provide(providers); rustc_mir_transform::provide(providers); rustc_monomorphize::provide(providers); - rustc_privacy::provide(providers); + rustc_privacy::provide(&mut providers.queries); rustc_query_impl::provide(providers); - rustc_resolve::provide(providers); - rustc_hir_analysis::provide(providers); - rustc_hir_typeck::provide(providers); - ty::provide(providers); - traits::provide(providers); - solve::provide(providers); - rustc_passes::provide(providers); - rustc_traits::provide(providers); - rustc_ty_utils::provide(providers); + rustc_resolve::provide(&mut providers.queries); + rustc_hir_analysis::provide(&mut providers.queries); + rustc_hir_typeck::provide(&mut providers.queries); + ty::provide(&mut providers.queries); + traits::provide(&mut providers.queries); + solve::provide(&mut providers.queries); + rustc_passes::provide(&mut providers.queries); + rustc_traits::provide(&mut providers.queries); + rustc_ty_utils::provide(&mut providers.queries); rustc_metadata::provide(providers); - rustc_lint::provide(providers); - rustc_symbol_mangling::provide(providers); + rustc_lint::provide(&mut providers.queries); + rustc_symbol_mangling::provide(&mut providers.queries); rustc_codegen_ssa::provide(providers); *providers }); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 0de54cf874338..af6df0cd6eb61 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -585,6 +585,6 @@ const SYMBOL_OFFSET: u8 = 1; const SYMBOL_PREDEFINED: u8 = 2; pub fn provide(providers: &mut Providers) { - encoder::provide(providers); + encoder::provide(&mut providers.queries); decoder::provide(providers); } diff --git a/compiler/rustc_middle/src/util/mod.rs b/compiler/rustc_middle/src/util/mod.rs index 85519fb0a7d2c..d5076a278eabf 100644 --- a/compiler/rustc_middle/src/util/mod.rs +++ b/compiler/rustc_middle/src/util/mod.rs @@ -6,20 +6,3 @@ pub struct Providers { pub extern_queries: crate::query::ExternProviders, pub hooks: crate::hooks::Providers, } - -/// Backwards compatibility hack to keep the diff small. This -/// gives direct access to the `queries` field's fields, which -/// are what almost everything wants access to. -impl std::ops::DerefMut for Providers { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.queries - } -} - -impl std::ops::Deref for Providers { - type Target = crate::query::Providers; - - fn deref(&self) -> &Self::Target { - &self.queries - } -} diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 410ea791ac5ca..91cc4dfa665f4 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -23,12 +23,12 @@ use rustc_middle::util::Providers; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn provide(providers: &mut Providers) { - providers.check_match = thir::pattern::check_match; - providers.lit_to_const = thir::constant::lit_to_const; - providers.closure_saved_names_of_captured_variables = + providers.queries.check_match = thir::pattern::check_match; + providers.queries.lit_to_const = thir::constant::lit_to_const; + providers.queries.closure_saved_names_of_captured_variables = builder::closure_saved_names_of_captured_variables; - providers.check_unsafety = check_unsafety::check_unsafety; - providers.check_tail_calls = check_tail_calls::check_tail_calls; - providers.thir_body = thir::cx::thir_body; + providers.queries.check_unsafety = check_unsafety::check_unsafety; + providers.queries.check_tail_calls = check_tail_calls::check_tail_calls; + providers.queries.thir_body = thir::cx::thir_body; providers.hooks.build_mir_inner_impl = builder::build_mir_inner_impl; } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index c78b0adaf6f18..328a4b23c1751 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -206,9 +206,9 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn provide(providers: &mut Providers) { coverage::query::provide(providers); - ffi_unwind_calls::provide(providers); - shim::provide(providers); - cross_crate_inline::provide(providers); + ffi_unwind_calls::provide(&mut providers.queries); + shim::provide(&mut providers.queries); + cross_crate_inline::provide(&mut providers.queries); providers.queries = query::Providers { mir_keys, mir_built, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 070db1ae6b5ee..ce17046969184 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1825,5 +1825,5 @@ pub(crate) fn collect_crate_mono_items<'tcx>( pub(crate) fn provide(providers: &mut Providers) { providers.hooks.should_codegen_locally = should_codegen_locally; - providers.items_of_instance = items_of_instance; + providers.queries.items_of_instance = items_of_instance; } diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 5b4f74ca6a708..56c74b693fb70 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -52,5 +52,5 @@ fn custom_coerce_unsize_info<'tcx>( pub fn provide(providers: &mut Providers) { partitioning::provide(providers); - mono_checks::provide(providers); + mono_checks::provide(&mut providers.queries); } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 13d7f6a25f76a..a86230e9ab22c 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -1313,12 +1313,12 @@ fn dump_mono_items_stats<'tcx>( } pub(crate) fn provide(providers: &mut Providers) { - providers.collect_and_partition_mono_items = collect_and_partition_mono_items; + providers.queries.collect_and_partition_mono_items = collect_and_partition_mono_items; - providers.is_codegened_item = + providers.queries.is_codegened_item = |tcx, def_id| tcx.collect_and_partition_mono_items(()).all_mono_items.contains(&def_id); - providers.codegen_unit = |tcx, name| { + providers.queries.codegen_unit = |tcx, name| { tcx.collect_and_partition_mono_items(()) .codegen_units .iter() @@ -1326,7 +1326,7 @@ pub(crate) fn provide(providers: &mut Providers) { .unwrap_or_else(|| panic!("failed to find cgu with name {name:?}")) }; - providers.size_estimate = |tcx, instance| { + providers.queries.size_estimate = |tcx, instance| { match instance.def { // "Normal" functions size estimate: the number of // statements, plus one for the terminator. diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 865f2a9c3b8bb..d371589cba6ca 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -9,7 +9,7 @@ #![feature(map_try_insert)] // tidy-alphabetical-end -use rustc_middle::util::Providers; +use rustc_middle::query::Providers; pub mod abi_test; mod check_attr; diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index fb20889632840..413163290ee30 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -297,14 +297,15 @@ pub(crate) fn create_config( override_queries: Some(|_sess, providers| { // We do not register late module lints, so this only runs `MissingDoc`. // Most lints will require typechecking, so just don't run them. - providers.lint_mod = |tcx, module_def_id| late_lint_mod(tcx, module_def_id, MissingDoc); + providers.queries.lint_mod = + |tcx, module_def_id| late_lint_mod(tcx, module_def_id, MissingDoc); // hack so that `used_trait_imports` won't try to call typeck - providers.used_trait_imports = |_, _| { + providers.queries.used_trait_imports = |_, _| { static EMPTY_SET: LazyLock> = LazyLock::new(UnordSet::default); &EMPTY_SET }; // In case typeck does end up being called, don't ICE in case there were name resolution errors - providers.typeck = move |tcx, def_id| { + providers.queries.typeck = move |tcx, def_id| { // Closures' tables come from their outermost function, // as they are part of the same "inference environment". // This avoids emitting errors for the parent twice (see similar code in `typeck_with_fallback`) @@ -316,7 +317,7 @@ pub(crate) fn create_config( let body = tcx.hir_body_owned_by(def_id); debug!("visiting body for {def_id:?}"); EmitIgnoredResolutionErrors::new(tcx).visit_body(body); - (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id) + (rustc_interface::DEFAULT_QUERY_PROVIDERS.queries.typeck)(tcx, def_id) }; }), extra_symbols: Vec::new(), diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 19fbf90246c93..9816061a8ecae 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -305,7 +305,7 @@ impl rustc_driver::Callbacks for MiriDepCompilerCalls { config.override_queries = Some(|_, local_providers| { // We need to add #[used] symbols to exported_symbols for `lookup_link_section`. // FIXME handle this somehow in rustc itself to avoid this hack. - local_providers.exported_non_generic_symbols = |tcx, LocalCrate| { + local_providers.queries.exported_non_generic_symbols = |tcx, LocalCrate| { let reachable_set = tcx .with_stable_hashing_context(|hcx| tcx.reachable_set(()).to_sorted(&hcx, true)); tcx.arena.alloc_from_iter( diff --git a/tests/ui-fulldeps/obtain-borrowck.rs b/tests/ui-fulldeps/obtain-borrowck.rs index 08213fd75880f..a562d0ccd3df3 100644 --- a/tests/ui-fulldeps/obtain-borrowck.rs +++ b/tests/ui-fulldeps/obtain-borrowck.rs @@ -114,7 +114,7 @@ impl rustc_driver::Callbacks for CompilerCalls { } fn override_queries(_session: &Session, local: &mut Providers) { - local.mir_borrowck = mir_borrowck; + local.queries.mir_borrowck = mir_borrowck; } // Since mir_borrowck does not have access to any other state, we need to use a @@ -142,8 +142,8 @@ fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ProvidedValue<'t } }); let mut providers = Providers::default(); - rustc_borrowck::provide(&mut providers); - let original_mir_borrowck = providers.mir_borrowck; + rustc_borrowck::provide(&mut providers.queries); + let original_mir_borrowck = providers.queries.mir_borrowck; original_mir_borrowck(tcx, def_id) }