From bcde3fc78018524e70284166f4b712e4f73ba9a3 Mon Sep 17 00:00:00 2001 From: enthropy7 <221884178+enthropy7@users.noreply.github.com> Date: Tue, 27 Jan 2026 17:13:42 +0300 Subject: [PATCH 01/10] fix refining_impl_trait suggestion with return_type_notation --- .../src/check/compare_impl_item/refine.rs | 14 ++++++++++- compiler/rustc_hir_analysis/src/errors.rs | 4 ++-- .../async-example-desugared-boxed.stderr | 2 +- .../async-example-desugared-manual.stderr | 2 +- .../bad-item-bound-within-rpitit.stderr | 2 +- ...e-to-map-to-reearlybound-ice-108580.stderr | 5 ++-- tests/ui/impl-trait/in-trait/foreign.stderr | 4 ++-- .../in-trait/refine-return-type-notation.rs | 13 ++++++++++ .../refine-return-type-notation.stderr | 24 +++++++++++++++++++ 9 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 tests/ui/impl-trait/in-trait/refine-return-type-notation.rs create mode 100644 tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index c20e5146546a2..31104411ab55b 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -6,6 +6,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE}; use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::print::{with_no_trimmed_paths, with_types_for_signature}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, @@ -332,6 +333,17 @@ fn report_mismatched_rpitit_signature<'tcx>( hir::FnRetTy::Return(ty) => ty.span, }); + // Use ForSignature mode to ensure RPITITs are printed as `impl Trait` rather than + // `impl Trait { T::method(..) }` when RTN is enabled. + // + // We use `with_no_trimmed_paths!` to avoid triggering the `trimmed_def_paths` query, + // which requires diagnostic context (via `must_produce_diag`). Since we're formatting + // the type before creating the diagnostic, we need to avoid this query. This is the + // standard approach used elsewhere in the compiler for formatting types in suggestions + // (e.g., see `rustc_hir_typeck/src/demand.rs`). + let return_ty_suggestion = + with_no_trimmed_paths!(with_types_for_signature!(format!("{return_ty}"))); + let span = unmatched_bound.unwrap_or(span); tcx.emit_node_span_lint( if is_internal { REFINING_IMPL_TRAIT_INTERNAL } else { REFINING_IMPL_TRAIT_REACHABLE }, @@ -342,7 +354,7 @@ fn report_mismatched_rpitit_signature<'tcx>( trait_return_span, pre, post, - return_ty, + return_ty: return_ty_suggestion, unmatched_bound, }, ); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 6a23b42ae0981..990c762135b1c 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1122,7 +1122,7 @@ pub(crate) struct UnusedAssociatedTypeBounds { #[note( "we are soliciting feedback, see issue #121718 for more information" )] -pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { +pub(crate) struct ReturnPositionImplTraitInTraitRefined { #[suggestion( "replace the return type so that it matches the trait", applicability = "maybe-incorrect", @@ -1136,7 +1136,7 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { pub pre: &'static str, pub post: &'static str, - pub return_ty: Ty<'tcx>, + pub return_ty: String, } #[derive(LintDiagnostic)] diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr index d3765a7e6e6fd..327ac40503ac0 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr @@ -18,7 +18,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn foo(&self) -> Pin + '_>> { -LL + fn foo(&self) -> impl Future { +LL + fn foo(&self) -> impl std::future::Future { | warning: 1 warning emitted diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr index 3328dea37fe4d..983c946d2a70d 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr @@ -18,7 +18,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn foo(&self) -> MyFuture { -LL + fn foo(&self) -> impl Future { +LL + fn foo(&self) -> impl std::future::Future { | warning: 1 warning emitted diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr index 8bc3c8b647c08..29975bdfcce8c 100644 --- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr @@ -29,7 +29,7 @@ LL | fn iter(&self) -> impl 'a + Iterator> { help: replace the return type so that it matches the trait | LL - fn iter(&self) -> impl 'a + Iterator> { -LL + fn iter(&self) -> impl Iterator::Item<'_>> + '_ { +LL + fn iter(&self) -> impl std::iter::Iterator::Item<'_>> + '_ { | error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr b/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr index 0a73a36378601..f44b34e38cfd6 100644 --- a/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr +++ b/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr @@ -12,8 +12,9 @@ LL | fn bar(&self) -> impl Iterator + '_ { = note: `#[warn(refining_impl_trait_internal)]` (part of `#[warn(refining_impl_trait)]`) on by default help: replace the return type so that it matches the trait | -LL | fn bar(&self) -> impl Iterator + '_ { - | +++++++++++++++++++ +LL - fn bar(&self) -> impl Iterator + '_ { +LL + fn bar(&self) -> impl std::iter::Iterator + '_ { + | warning: 1 warning emitted diff --git a/tests/ui/impl-trait/in-trait/foreign.stderr b/tests/ui/impl-trait/in-trait/foreign.stderr index 8801ccc68b3be..f1c76f743c6e2 100644 --- a/tests/ui/impl-trait/in-trait/foreign.stderr +++ b/tests/ui/impl-trait/in-trait/foreign.stderr @@ -15,7 +15,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn bar(self) -> Arc { -LL + fn bar(self) -> impl Deref { +LL + fn bar(self) -> impl std::ops::Deref { | warning: impl trait in impl method signature does not match trait method signature @@ -34,7 +34,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn bar(self) -> Arc { -LL + fn bar(self) -> impl Deref { +LL + fn bar(self) -> impl std::ops::Deref { | warning: 2 warnings emitted diff --git a/tests/ui/impl-trait/in-trait/refine-return-type-notation.rs b/tests/ui/impl-trait/in-trait/refine-return-type-notation.rs new file mode 100644 index 0000000000000..281f4c73ac21a --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-return-type-notation.rs @@ -0,0 +1,13 @@ +#![feature(return_type_notation)] +#![deny(refining_impl_trait)] + +trait Trait { + fn f() -> impl Sized; +} + +impl Trait for () { + fn f() {} + //~^ ERROR impl trait in impl method signature does not match trait method signature +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr b/tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr new file mode 100644 index 0000000000000..1f9a5b9e87492 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr @@ -0,0 +1,24 @@ +error: impl trait in impl method signature does not match trait method signature + --> $DIR/refine-return-type-notation.rs:9:5 + | +LL | fn f() -> impl Sized; + | ---------- return type from trait method defined here +... +LL | fn f() {} + | ^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information +note: the lint level is defined here + --> $DIR/refine-return-type-notation.rs:2:9 + | +LL | #![deny(refining_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(refining_impl_trait_internal)]` implied by `#[deny(refining_impl_trait)]` +help: replace the return type so that it matches the trait + | +LL | fn f()-> impl Sized {} + | +++++++++++++ + +error: aborting due to 1 previous error + From f0f849d96ff7c1ea57eca1de63a966e8f832baf5 Mon Sep 17 00:00:00 2001 From: Shinika Balasundar <98338989+shibcreate@users.noreply.github.com> Date: Sat, 14 Feb 2026 20:14:50 -0800 Subject: [PATCH 02/10] Add direct link to rustc-dev-guide in README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 611260470f12b..ed35016eb3a23 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ See https://www.rust-lang.org/community for a list of chat platforms and forums. See [CONTRIBUTING.md](CONTRIBUTING.md). +For a detailed explanation of the compiler's architecture and how to begin contributing, see the [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/). + ## License Rust is primarily distributed under the terms of both the MIT license and the From 9f0a41009648ac9065e22460ee9b3d0f21714a29 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 22 Feb 2026 10:07:02 +0100 Subject: [PATCH 03/10] Revert "Stabilize `str_as_str`" --- library/alloctests/tests/lib.rs | 1 + library/core/src/bstr/mod.rs | 2 ++ library/core/src/ffi/c_str.rs | 3 +-- library/core/src/slice/mod.rs | 6 ++---- library/core/src/str/mod.rs | 3 +-- library/std/src/ffi/os_str.rs | 3 +-- library/std/src/path.rs | 3 +-- 7 files changed, 9 insertions(+), 12 deletions(-) diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index f18d6e1bb3794..699a5010282b0 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -33,6 +33,7 @@ #![feature(thin_box)] #![feature(drain_keep_rest)] #![feature(local_waker)] +#![feature(str_as_str)] #![feature(strict_provenance_lints)] #![feature(string_replace_in_place)] #![feature(vec_deque_truncate_front)] diff --git a/library/core/src/bstr/mod.rs b/library/core/src/bstr/mod.rs index 3e3b78b452e01..34e1ea66c99ad 100644 --- a/library/core/src/bstr/mod.rs +++ b/library/core/src/bstr/mod.rs @@ -74,6 +74,7 @@ impl ByteStr { /// it helps dereferencing other "container" types, /// for example `Box` or `Arc`. #[inline] + // #[unstable(feature = "str_as_str", issue = "130366")] #[unstable(feature = "bstr", issue = "134915")] pub const fn as_byte_str(&self) -> &ByteStr { self @@ -85,6 +86,7 @@ impl ByteStr { /// it helps dereferencing other "container" types, /// for example `Box` or `MutexGuard`. #[inline] + // #[unstable(feature = "str_as_str", issue = "130366")] #[unstable(feature = "bstr", issue = "134915")] pub const fn as_mut_byte_str(&mut self) -> &mut ByteStr { self diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 8097066a57339..621277179bb38 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -655,8 +655,7 @@ impl CStr { /// it helps dereferencing other string-like types to string slices, /// for example references to `Box` or `Arc`. #[inline] - #[stable(feature = "str_as_str", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "str_as_str", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "str_as_str", issue = "130366")] pub const fn as_c_str(&self) -> &CStr { self } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index ac3088142f7df..36dd4d6782ac1 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -5337,8 +5337,7 @@ impl [T] { /// it helps dereferencing other "container" types to slices, /// for example `Box<[T]>` or `Arc<[T]>`. #[inline] - #[stable(feature = "str_as_str", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "str_as_str", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "str_as_str", issue = "130366")] pub const fn as_slice(&self) -> &[T] { self } @@ -5349,8 +5348,7 @@ impl [T] { /// it helps dereferencing other "container" types to slices, /// for example `Box<[T]>` or `MutexGuard<[T]>`. #[inline] - #[stable(feature = "str_as_str", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "str_as_str", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "str_as_str", issue = "130366")] pub const fn as_mut_slice(&mut self) -> &mut [T] { self } diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 2d7fdb824d1f8..98354643aa405 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -3137,8 +3137,7 @@ impl str { /// it helps dereferencing other string-like types to string slices, /// for example references to `Box` or `Arc`. #[inline] - #[stable(feature = "str_as_str", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "str_as_str", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "str_as_str", issue = "130366")] pub const fn as_str(&self) -> &str { self } diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 6b4cf3cea831c..ca910153e5260 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -1285,8 +1285,7 @@ impl OsStr { /// it helps dereferencing other string-like types to string slices, /// for example references to `Box` or `Arc`. #[inline] - #[stable(feature = "str_as_str", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "str_as_str", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "str_as_str", issue = "130366")] pub const fn as_os_str(&self) -> &OsStr { self } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 712031ff7ccb1..bf27df7b04281 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -3235,8 +3235,7 @@ impl Path { /// it helps dereferencing other `PathBuf`-like types to `Path`s, /// for example references to `Box` or `Arc`. #[inline] - #[stable(feature = "str_as_str", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "str_as_str", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "str_as_str", issue = "130366")] pub const fn as_path(&self) -> &Path { self } From 51d72725a26a6b3480a15e7aeec69aea394c6874 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 22 Feb 2026 11:38:34 +0100 Subject: [PATCH 04/10] Add regression test --- tests/ui/resolve/slice-as-slice.rs | 26 ++++++++++++++++++++++++++ tests/ui/resolve/slice-as-slice.stderr | 17 +++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 tests/ui/resolve/slice-as-slice.rs create mode 100644 tests/ui/resolve/slice-as-slice.stderr diff --git a/tests/ui/resolve/slice-as-slice.rs b/tests/ui/resolve/slice-as-slice.rs new file mode 100644 index 0000000000000..04b8042bff921 --- /dev/null +++ b/tests/ui/resolve/slice-as-slice.rs @@ -0,0 +1,26 @@ +//@ check-pass +// This is a regression test for github.com/rust-lang/rust/issues/152961 +// This broke when a method `as_slice` was added on slices +// This pattern is used in the `rgb` crate + +struct Meow; + +trait ComponentSlice { + fn as_slice(&self) -> &[T]; +} + +impl ComponentSlice for [Meow] { + fn as_slice(&self) -> &[u8] { + todo!() + } +} + +fn a(data: &[Meow]) { + b(data.as_slice()); + //~^ WARN a method with this name may be added to the standard library in the future + //~| WARN once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior! +} + +fn b(_b: &[u8]) { } + +fn main() {} diff --git a/tests/ui/resolve/slice-as-slice.stderr b/tests/ui/resolve/slice-as-slice.stderr new file mode 100644 index 0000000000000..c93363431c595 --- /dev/null +++ b/tests/ui/resolve/slice-as-slice.stderr @@ -0,0 +1,17 @@ +warning: a method with this name may be added to the standard library in the future + --> $DIR/slice-as-slice.rs:19:12 + | +LL | b(data.as_slice()); + | ^^^^^^^^ + | + = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior! + = note: for more information, see issue #48919 + = help: call with fully qualified syntax `ComponentSlice::as_slice(...)` to keep using the current method + = note: `#[warn(unstable_name_collisions)]` (part of `#[warn(future_incompatible)]`) on by default +help: add `#![feature(str_as_str)]` to the crate attributes to enable `core::slice::::as_slice` + | +LL + #![feature(str_as_str)] + | + +warning: 1 warning emitted + From b56949bddf9988c263347d751953f88463a9d7ec Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 22 Feb 2026 15:05:23 +0100 Subject: [PATCH 05/10] extend unpin noalias tests to cover mutable references --- tests/codegen-llvm/function-arguments.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/codegen-llvm/function-arguments.rs b/tests/codegen-llvm/function-arguments.rs index 46e153a0cfc62..95edecfc6f79b 100644 --- a/tests/codegen-llvm/function-arguments.rs +++ b/tests/codegen-llvm/function-arguments.rs @@ -257,11 +257,11 @@ pub fn option_trait_borrow_mut(x: Option<&mut dyn Drop>) {} #[no_mangle] pub fn trait_raw(_: *const dyn Drop) {} +// Ensure that `Box` gets `noalias` when the right traits are present, but removing *either* `Unpin` +// or `UnsafeUnpin` is enough to lose the attribute. // CHECK: @trait_box(ptr noalias noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}}) #[no_mangle] pub fn trait_box(_: Box) {} - -// Ensure that removing *either* `Unpin` or `UnsafeUnpin` is enough to lose the attribute. // CHECK: @trait_box_pin1(ptr noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}}) #[no_mangle] pub fn trait_box_pin1(_: Box) {} @@ -269,6 +269,18 @@ pub fn trait_box_pin1(_: Box) {} #[no_mangle] pub fn trait_box_pin2(_: Box) {} +// Same for mutable references (with a non-zero minimal size so that we also see the +// `dereferenceable` disappear). +// CHECK: @trait_mutref(ptr noalias noundef align 4 dereferenceable(4){{( %_1.0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) +#[no_mangle] +pub fn trait_mutref(_: &mut (i32, dyn Drop + Unpin + UnsafeUnpin)) {} +// CHECK: @trait_mutref_pin1(ptr noundef nonnull align 4{{( %_1.0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) +#[no_mangle] +pub fn trait_mutref_pin1(_: &mut (i32, dyn Drop + Unpin)) {} +// CHECK: @trait_mutref_pin2(ptr noundef nonnull align 4{{( %_1.0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) +#[no_mangle] +pub fn trait_mutref_pin2(_: &mut (i32, dyn Drop + UnsafeUnpin)) {} + // CHECK: { ptr, ptr } @trait_option(ptr noalias noundef align 1 %x.0, ptr %x.1) #[no_mangle] pub fn trait_option( From febd3b9fe117fc6781a7b243f2459b5e053165f4 Mon Sep 17 00:00:00 2001 From: stellanomia Date: Mon, 23 Feb 2026 00:57:00 +0900 Subject: [PATCH 06/10] rustc_mir_transform: Remove redundant call to check_codegen_attributes_extra --- compiler/rustc_mir_transform/src/inline.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 179ada36be754..4e2d9130f2a4f 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -607,7 +607,6 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( let callee_attrs = callee_attrs.as_ref(); check_inline::is_inline_valid_on_fn(tcx, callsite.callee.def_id())?; check_codegen_attributes(inliner, callsite, callee_attrs)?; - inliner.check_codegen_attributes_extra(callee_attrs)?; let terminator = caller_body[callsite.block].terminator.as_ref().unwrap(); let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; From 14d29f9ae2b814bb547cf2b83b847703d2ac359e Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 7 Feb 2026 20:42:31 +0100 Subject: [PATCH 07/10] Stabilize `cfg_select` --- .../src/attributes/cfg_select.rs | 22 +++++------- ...sroot_tests-128bit-atomic-operations.patch | 2 +- compiler/rustc_data_structures/src/lib.rs | 2 +- compiler/rustc_feature/src/accepted.rs | 2 ++ compiler/rustc_feature/src/unstable.rs | 2 -- compiler/rustc_lint_defs/src/builtin.rs | 3 +- compiler/rustc_span/src/lib.rs | 2 +- library/core/src/lib.rs | 3 +- library/core/src/macros/mod.rs | 6 +--- library/core/src/prelude/v1.rs | 2 +- library/coretests/tests/lib.rs | 1 - library/panic_unwind/src/lib.rs | 1 - library/std/src/lib.rs | 3 +- library/std/src/prelude/v1.rs | 2 +- library/std/tests/env_modify.rs | 1 - library/std_detect/src/lib.rs | 2 +- library/unwind/src/lib.rs | 1 - src/tools/miri/src/lib.rs | 2 +- .../tests/pass/float_extra_rounding_error.rs | 1 - .../c-link-to-rust-va-list-fn/checkrust.rs | 1 - tests/ui/asm/cfg.rs | 1 - tests/ui/check-cfg/cfg-select.rs | 1 - tests/ui/check-cfg/cfg-select.stderr | 4 +-- .../feature-gates/feature-gate-cfg-select.rs | 11 ------ .../feature-gate-cfg-select.stderr | 25 -------------- tests/ui/macros/cfg_select.rs | 1 - tests/ui/macros/cfg_select.stderr | 34 +++++++++---------- tests/ui/macros/cfg_select_parse_error.rs | 1 - tests/ui/macros/cfg_select_parse_error.stderr | 4 +-- 29 files changed, 42 insertions(+), 101 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-cfg-select.rs delete mode 100644 tests/ui/feature-gates/feature-gate-cfg-select.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index b6cb5b4504ee1..7377159be370a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -128,20 +128,14 @@ pub fn parse_cfg_select( } } - if let Some(features) = features - && features.enabled(sym::cfg_select) - { - let it = branches - .reachable - .iter() - .map(|(entry, _, _)| CfgSelectPredicate::Cfg(entry.clone())) - .chain(branches.wildcard.as_ref().map(|(t, _, _)| CfgSelectPredicate::Wildcard(*t))) - .chain( - branches.unreachable.iter().map(|(entry, _, _)| CfgSelectPredicate::clone(entry)), - ); - - lint_unreachable(p, it, lint_node_id); - } + let it = branches + .reachable + .iter() + .map(|(entry, _, _)| CfgSelectPredicate::Cfg(entry.clone())) + .chain(branches.wildcard.as_ref().map(|(t, _, _)| CfgSelectPredicate::Wildcard(*t))) + .chain(branches.unreachable.iter().map(|(entry, _, _)| CfgSelectPredicate::clone(entry))); + + lint_unreachable(p, it, lint_node_id); Ok(branches) } diff --git a/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch index 6ed0b17f679ca..7ba4475e31454 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch @@ -17,8 +17,8 @@ index 1e336bf..35e6f54 100644 @@ -2,4 +2,3 @@ // tidy-alphabetical-start -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] - #![cfg_attr(test, feature(cfg_select))] #![feature(array_ptr_get)] + #![feature(array_try_from_fn)] diff --git a/coretests/tests/atomic.rs b/coretests/tests/atomic.rs index b735957..ea728b6 100644 --- a/coretests/tests/atomic.rs diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 594d6d294d75a..6bee338b23df2 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -11,6 +11,7 @@ #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] #![cfg_attr(bootstrap, feature(assert_matches))] +#![cfg_attr(bootstrap, feature(cfg_select))] #![cfg_attr(bootstrap, feature(cold_path))] #![cfg_attr(test, feature(test))] #![deny(unsafe_op_in_unsafe_fn)] @@ -18,7 +19,6 @@ #![feature(ascii_char)] #![feature(ascii_char_variants)] #![feature(auto_traits)] -#![feature(cfg_select)] #![feature(const_default)] #![feature(const_trait_impl)] #![feature(dropck_eyepatch)] diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 24f4ed327ec5d..aa3b15dd9e890 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -102,6 +102,8 @@ declare_features! ( (accepted, cfg_doctest, "1.40.0", Some(62210)), /// Enables `#[cfg(panic = "...")]` config key. (accepted, cfg_panic, "1.60.0", Some(77443)), + /// Provides a native way to easily manage multiple conditional flags without having to rewrite each clause multiple times. + (accepted, cfg_select, "CURRENT_RUSTC_VERSION", Some(115585)), /// Allows `cfg(target_abi = "...")`. (accepted, cfg_target_abi, "1.78.0", Some(80970)), /// Allows `cfg(target_feature = "...")`. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 5becbac186766..1d123385961aa 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -388,8 +388,6 @@ declare_features! ( (unstable, cfg_sanitize, "1.41.0", Some(39699)), /// Allows `cfg(sanitizer_cfi_generalize_pointers)` and `cfg(sanitizer_cfi_normalize_integers)`. (unstable, cfg_sanitizer_cfi, "1.77.0", Some(89653)), - /// Provides a native way to easily manage multiple conditional flags without having to rewrite each clause multiple times. - (unstable, cfg_select, "CURRENT_RUSTC_VERSION", Some(115585)), /// Allows `cfg(target(abi = "..."))`. (unstable, cfg_target_compact, "1.63.0", Some(96901)), /// Allows `cfg(target_has_atomic_load_store = "...")`. diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 2bec9273d38f6..c20c9dca346fd 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -864,7 +864,7 @@ declare_lint! { /// ### Example /// /// ```rust - /// #![feature(cfg_select)] + /// # #![cfg_attr(bootstrap, feature(cfg_select))] /// cfg_select! { /// _ => (), /// windows => (), @@ -882,7 +882,6 @@ declare_lint! { pub UNREACHABLE_CFG_SELECT_PREDICATES, Warn, "detects unreachable configuration predicates in the cfg_select macro", - @feature_gate = cfg_select; } declare_lint! { diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index dea077ce30cc3..3345f6ef31b1f 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -17,9 +17,9 @@ // tidy-alphabetical-start #![allow(internal_features)] +#![cfg_attr(bootstrap, feature(cfg_select))] #![cfg_attr(bootstrap, feature(if_let_guard))] #![cfg_attr(target_arch = "loongarch64", feature(stdarch_loongarch))] -#![feature(cfg_select)] #![feature(core_io_borrowed_buf)] #![feature(map_try_insert)] #![feature(negative_impls)] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 63fa54be3852b..ed1b73c6e3d96 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -98,7 +98,6 @@ // tidy-alphabetical-start #![feature(asm_experimental_arch)] #![feature(bstr_internals)] -#![feature(cfg_select)] #![feature(cfg_target_has_reliable_f16_f128)] #![feature(const_carrying_mul_add)] #![feature(const_cmp)] @@ -227,7 +226,7 @@ pub mod autodiff { #[unstable(feature = "contracts", issue = "128044")] pub mod contracts; -#[unstable(feature = "cfg_select", issue = "115585")] +#[stable(feature = "cfg_select", since = "CURRENT_RUSTC_VERSION")] pub use crate::macros::cfg_select; #[macro_use] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index cdbb8c300455d..28eefd0013ca5 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -206,8 +206,6 @@ pub macro assert_matches { /// # Example /// /// ``` -/// #![feature(cfg_select)] -/// /// cfg_select! { /// unix => { /// fn foo() { /* unix specific functionality */ } @@ -225,14 +223,12 @@ pub macro assert_matches { /// right-hand side: /// /// ``` -/// #![feature(cfg_select)] -/// /// let _some_string = cfg_select! { /// unix => "With great power comes great electricity bills", /// _ => { "Behind every successful diet is an unwatched pizza" } /// }; /// ``` -#[unstable(feature = "cfg_select", issue = "115585")] +#[stable(feature = "cfg_select", since = "CURRENT_RUSTC_VERSION")] #[rustc_diagnostic_item = "cfg_select"] #[rustc_builtin_macro] pub macro cfg_select($($tt:tt)*) { diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index 354be271ff131..17928b1e9cb31 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -80,7 +80,7 @@ mod ambiguous_macros_only { #[doc(no_inline)] pub use self::ambiguous_macros_only::{env, panic}; -#[unstable(feature = "cfg_select", issue = "115585")] +#[stable(feature = "cfg_select", since = "CURRENT_RUSTC_VERSION")] #[doc(no_inline)] pub use crate::cfg_select; diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 85ee7cff68266..7cd946dc9a03f 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -1,6 +1,5 @@ // tidy-alphabetical-start #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] -#![cfg_attr(test, feature(cfg_select))] #![feature(array_ptr_get)] #![feature(array_try_from_fn)] #![feature(array_try_map)] diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 83f2a3b2c53f4..5372c44cedf75 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -15,7 +15,6 @@ #![unstable(feature = "panic_unwind", issue = "32837")] #![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] #![feature(cfg_emscripten_wasm_eh)] -#![feature(cfg_select)] #![feature(core_intrinsics)] #![feature(panic_unwind)] #![feature(staged_api)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 5620ef0254aa7..ed1c1a89bd410 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -322,7 +322,6 @@ #![feature(bstr)] #![feature(bstr_internals)] #![feature(cast_maybe_uninit)] -#![feature(cfg_select)] #![feature(char_internals)] #![feature(clone_to_uninit)] #![feature(const_convert)] @@ -695,7 +694,7 @@ mod panicking; #[allow(dead_code, unused_attributes, fuzzy_provenance_casts, unsafe_op_in_unsafe_fn)] mod backtrace_rs; -#[unstable(feature = "cfg_select", issue = "115585")] +#[stable(feature = "cfg_select", since = "CURRENT_RUSTC_VERSION")] pub use core::cfg_select; #[unstable( feature = "concat_bytes", diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index af9d28ebad356..f17f11dec7f62 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -79,7 +79,7 @@ mod ambiguous_macros_only { #[doc(no_inline)] pub use self::ambiguous_macros_only::{vec, panic}; -#[unstable(feature = "cfg_select", issue = "115585")] +#[stable(feature = "cfg_select", since = "CURRENT_RUSTC_VERSION")] #[doc(no_inline)] pub use core::prelude::v1::cfg_select; diff --git a/library/std/tests/env_modify.rs b/library/std/tests/env_modify.rs index 4cd87bf7a0027..3404ca537acca 100644 --- a/library/std/tests/env_modify.rs +++ b/library/std/tests/env_modify.rs @@ -1,6 +1,5 @@ // These tests are in a separate integration test as they modify the environment, // and would otherwise cause some other tests to fail. -#![feature(cfg_select)] use std::env::*; use std::ffi::{OsStr, OsString}; diff --git a/library/std_detect/src/lib.rs b/library/std_detect/src/lib.rs index 5e1d21bbfd17d..f9d79df670a0f 100644 --- a/library/std_detect/src/lib.rs +++ b/library/std_detect/src/lib.rs @@ -15,7 +15,7 @@ //! * `s390x`: [`is_s390x_feature_detected`] #![unstable(feature = "stdarch_internal", issue = "none")] -#![feature(staged_api, cfg_select, doc_cfg, allow_internal_unstable)] +#![feature(staged_api, doc_cfg, allow_internal_unstable)] #![deny(rust_2018_idioms)] #![allow(clippy::shadow_reuse)] #![cfg_attr(test, allow(unused_imports))] diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 1e68eda52064e..cce6ca748cccd 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -1,7 +1,6 @@ #![no_std] #![unstable(feature = "panic_unwind", issue = "32837")] #![feature(cfg_emscripten_wasm_eh)] -#![feature(cfg_select)] #![feature(link_cfg)] #![feature(staged_api)] #![cfg_attr( diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 232a24306d65e..32cadddc33aa3 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -1,6 +1,5 @@ #![cfg_attr(bootstrap, feature(if_let_guard))] #![feature(abort_unwind)] -#![feature(cfg_select)] #![feature(rustc_private)] #![feature(float_gamma)] #![feature(float_erf)] @@ -17,6 +16,7 @@ #![feature(derive_coerce_pointee)] #![feature(arbitrary_self_types)] #![feature(iter_advance_by)] +#![cfg_attr(bootstrap, feature(cfg_select))] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, diff --git a/src/tools/miri/tests/pass/float_extra_rounding_error.rs b/src/tools/miri/tests/pass/float_extra_rounding_error.rs index 24d7cf2cceee2..fc8190b7dec26 100644 --- a/src/tools/miri/tests/pass/float_extra_rounding_error.rs +++ b/src/tools/miri/tests/pass/float_extra_rounding_error.rs @@ -2,7 +2,6 @@ //@revisions: random max none //@[max]compile-flags: -Zmiri-max-extra-rounding-error //@[none]compile-flags: -Zmiri-no-extra-rounding-error -#![feature(cfg_select)] use std::collections::HashSet; use std::hint::black_box; diff --git a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs index dd2d094709942..97506cdd592b6 100644 --- a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs +++ b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs @@ -1,6 +1,5 @@ #![crate_type = "staticlib"] #![feature(c_variadic)] -#![feature(cfg_select)] use std::ffi::{CStr, CString, VaList, c_char, c_double, c_int, c_long, c_longlong}; diff --git a/tests/ui/asm/cfg.rs b/tests/ui/asm/cfg.rs index 90b1b3d6ee650..d7a2c78f58d26 100644 --- a/tests/ui/asm/cfg.rs +++ b/tests/ui/asm/cfg.rs @@ -3,7 +3,6 @@ //@ revisions: reva revb //@ only-x86_64 //@ run-pass -#![feature(cfg_select)] use std::arch::{asm, naked_asm}; diff --git a/tests/ui/check-cfg/cfg-select.rs b/tests/ui/check-cfg/cfg-select.rs index ffa5e40bff085..b2638b2529df3 100644 --- a/tests/ui/check-cfg/cfg-select.rs +++ b/tests/ui/check-cfg/cfg-select.rs @@ -1,6 +1,5 @@ //@ check-pass -#![feature(cfg_select)] #![crate_type = "lib"] cfg_select! { diff --git a/tests/ui/check-cfg/cfg-select.stderr b/tests/ui/check-cfg/cfg-select.stderr index 23ed5918e71ce..e8b6fe6eff104 100644 --- a/tests/ui/check-cfg/cfg-select.stderr +++ b/tests/ui/check-cfg/cfg-select.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `invalid_cfg1` - --> $DIR/cfg-select.rs:8:5 + --> $DIR/cfg-select.rs:7:5 | LL | invalid_cfg1 => {} | ^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | invalid_cfg1 => {} = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `invalid_cfg2` - --> $DIR/cfg-select.rs:14:5 + --> $DIR/cfg-select.rs:13:5 | LL | invalid_cfg2 => {} | ^^^^^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-cfg-select.rs b/tests/ui/feature-gates/feature-gate-cfg-select.rs deleted file mode 100644 index 0963ed0015082..0000000000000 --- a/tests/ui/feature-gates/feature-gate-cfg-select.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![warn(unreachable_cfg_select_predicates)] -//~^ WARN unknown lint: `unreachable_cfg_select_predicates` - -cfg_select! { - //~^ ERROR use of unstable library feature `cfg_select` - _ => {} - // With the feature enabled, this branch would trip the unreachable_cfg_select_predicate lint. - true => {} -} - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-cfg-select.stderr b/tests/ui/feature-gates/feature-gate-cfg-select.stderr deleted file mode 100644 index 0fdce49751645..0000000000000 --- a/tests/ui/feature-gates/feature-gate-cfg-select.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0658]: use of unstable library feature `cfg_select` - --> $DIR/feature-gate-cfg-select.rs:4:1 - | -LL | cfg_select! { - | ^^^^^^^^^^ - | - = note: see issue #115585 for more information - = help: add `#![feature(cfg_select)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -warning: unknown lint: `unreachable_cfg_select_predicates` - --> $DIR/feature-gate-cfg-select.rs:1:9 - | -LL | #![warn(unreachable_cfg_select_predicates)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `unreachable_cfg_select_predicates` lint is unstable - = note: see issue #115585 for more information - = help: add `#![feature(cfg_select)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: `#[warn(unknown_lints)]` on by default - -error: aborting due to 1 previous error; 1 warning emitted - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 693e27daad7ad..113cff38a3a93 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -1,4 +1,3 @@ -#![feature(cfg_select)] #![crate_type = "lib"] #![warn(unreachable_cfg_select_predicates)] // Unused warnings are disabled by default in UI tests. diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index 2da0c21694972..d2803964e00c2 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -1,5 +1,5 @@ error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:162:1 + --> $DIR/cfg_select.rs:161:1 | LL | / cfg_select! { LL | | @@ -8,55 +8,55 @@ LL | | } | |_^ error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:167:1 + --> $DIR/cfg_select.rs:166:1 | LL | cfg_select! {} | ^^^^^^^^^^^^^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>` - --> $DIR/cfg_select.rs:171:5 + --> $DIR/cfg_select.rs:170:5 | LL | => {} | ^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression - --> $DIR/cfg_select.rs:176:5 + --> $DIR/cfg_select.rs:175:5 | LL | () => {} | ^^ expressions are not allowed here error[E0539]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:181:5 + --> $DIR/cfg_select.rs:180:5 | LL | "str" => {} | ^^^^^ expected a valid identifier here error[E0539]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:186:5 + --> $DIR/cfg_select.rs:185:5 | LL | a::b => {} | ^^^^ expected a valid identifier here error[E0537]: invalid predicate `a` - --> $DIR/cfg_select.rs:191:5 + --> $DIR/cfg_select.rs:190:5 | LL | a() => {} | ^^^ error: expected one of `(`, `::`, `=>`, or `=`, found `+` - --> $DIR/cfg_select.rs:196:7 + --> $DIR/cfg_select.rs:195:7 | LL | a + 1 => {} | ^ expected one of `(`, `::`, `=>`, or `=` error: expected one of `(`, `::`, `=>`, or `=`, found `!` - --> $DIR/cfg_select.rs:202:8 + --> $DIR/cfg_select.rs:201:8 | LL | cfg!() => {} | ^ expected one of `(`, `::`, `=>`, or `=` warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:137:5 + --> $DIR/cfg_select.rs:136:5 | LL | _ => {} | - always matches @@ -64,13 +64,13 @@ LL | true => {} | ^^^^ this configuration predicate is never reached | note: the lint level is defined here - --> $DIR/cfg_select.rs:3:9 + --> $DIR/cfg_select.rs:2:9 | LL | #![warn(unreachable_cfg_select_predicates)] // Unused warnings are disabled by default in UI tests. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:143:5 + --> $DIR/cfg_select.rs:142:5 | LL | true => {} | ---- always matches @@ -78,25 +78,25 @@ LL | _ => {} | ^ this configuration predicate is never reached warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:150:5 + --> $DIR/cfg_select.rs:149:5 | LL | _ => {} | ^ this configuration predicate is never reached warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:156:5 + --> $DIR/cfg_select.rs:155:5 | LL | test => {} | ^^^^ this configuration predicate is never reached warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:158:5 + --> $DIR/cfg_select.rs:157:5 | LL | _ => {} | ^ this configuration predicate is never reached warning: unexpected `cfg` condition name: `a` - --> $DIR/cfg_select.rs:196:5 + --> $DIR/cfg_select.rs:195:5 | LL | a + 1 => {} | ^ help: found config with similar value: `target_feature = "a"` @@ -107,7 +107,7 @@ LL | a + 1 => {} = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `cfg` - --> $DIR/cfg_select.rs:202:5 + --> $DIR/cfg_select.rs:201:5 | LL | cfg!() => {} | ^^^ diff --git a/tests/ui/macros/cfg_select_parse_error.rs b/tests/ui/macros/cfg_select_parse_error.rs index 90fcb2309b348..049a87c896564 100644 --- a/tests/ui/macros/cfg_select_parse_error.rs +++ b/tests/ui/macros/cfg_select_parse_error.rs @@ -1,4 +1,3 @@ -#![feature(cfg_select)] #![crate_type = "lib"] // Check that parse errors in arms that are not selected are still reported. diff --git a/tests/ui/macros/cfg_select_parse_error.stderr b/tests/ui/macros/cfg_select_parse_error.stderr index d4c86c3ceade1..d94b5d784866e 100644 --- a/tests/ui/macros/cfg_select_parse_error.stderr +++ b/tests/ui/macros/cfg_select_parse_error.stderr @@ -1,5 +1,5 @@ error: Rust has no postfix increment operator - --> $DIR/cfg_select_parse_error.rs:8:22 + --> $DIR/cfg_select_parse_error.rs:7:22 | LL | false => { 1 ++ 2 } | ^^ not a valid postfix operator @@ -11,7 +11,7 @@ LL + false => { { let tmp = 1 ; 1 += 1; tmp } 2 } | error: Rust has no postfix increment operator - --> $DIR/cfg_select_parse_error.rs:15:29 + --> $DIR/cfg_select_parse_error.rs:14:29 | LL | false => { fn foo() { 1 +++ 2 } } | ^^ not a valid postfix operator From 912c7d31d24405bf66af17c84af51208de6b691b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 22 Feb 2026 19:50:35 +0100 Subject: [PATCH 08/10] Use HashStable derive in more places --- compiler/rustc_data_structures/src/lib.rs | 3 +++ .../src/sorted_map/index_map.rs | 23 ++++--------------- compiler/rustc_data_structures/src/svh.rs | 23 ++++++++++--------- compiler/rustc_hir/src/diagnostic_items.rs | 12 +++------- compiler/rustc_macros/src/lib.rs | 2 +- .../rustc_middle/src/dep_graph/dep_node.rs | 13 ++++------- compiler/rustc_middle/src/mir/mod.rs | 21 +---------------- compiler/rustc_span/src/lib.rs | 8 +------ compiler/rustc_target/src/target_features.rs | 20 ++-------------- 9 files changed, 31 insertions(+), 94 deletions(-) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 594d6d294d75a..5c9678ca674de 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -47,6 +47,9 @@ use std::fmt; #[cfg(not(bootstrap))] pub use std::{assert_matches, debug_assert_matches}; +// This allows derive macros to reference this crate +extern crate self as rustc_data_structures; + pub use atomic_ref::AtomicRef; pub use ena::{snapshot_vec, undo_log, unify}; // Re-export `hashbrown::hash_table`, because it's part of our API diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs index b38b09d60ebf0..30485a289b6b7 100644 --- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs @@ -3,8 +3,7 @@ use std::hash::{Hash, Hasher}; use rustc_index::{Idx, IndexVec}; - -use crate::stable_hasher::{HashStable, StableHasher}; +use rustc_macros::HashStable_NoContext; /// An indexed multi-map that preserves insertion order while permitting both *O*(log *n*) lookup of /// an item by key and *O*(1) lookup by index. @@ -24,11 +23,13 @@ use crate::stable_hasher::{HashStable, StableHasher}; /// in-place. /// /// [`SortedMap`]: super::SortedMap -#[derive(Clone, Debug)] +#[derive(Clone, Debug, HashStable_NoContext)] pub struct SortedIndexMultiMap { /// The elements of the map in insertion order. items: IndexVec, + // We can ignore this field because it is not observable from the outside. + #[stable_hasher(ignore)] /// Indices of the items in the set, sorted by the item's key. idx_sorted_by_item_key: Vec, } @@ -126,22 +127,6 @@ where } } -impl HashStable for SortedIndexMultiMap -where - K: HashStable, - V: HashStable, -{ - fn hash_stable(&self, ctx: &mut C, hasher: &mut StableHasher) { - let SortedIndexMultiMap { - items, - // We can ignore this field because it is not observable from the outside. - idx_sorted_by_item_key: _, - } = self; - - items.hash_stable(ctx, hasher) - } -} - impl FromIterator<(K, V)> for SortedIndexMultiMap { fn from_iter(iter: J) -> Self where diff --git a/compiler/rustc_data_structures/src/svh.rs b/compiler/rustc_data_structures/src/svh.rs index f51fcb8ed22d3..68b224676aec7 100644 --- a/compiler/rustc_data_structures/src/svh.rs +++ b/compiler/rustc_data_structures/src/svh.rs @@ -7,12 +7,21 @@ use std::fmt; -use rustc_macros::{Decodable_NoContext, Encodable_NoContext}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use crate::fingerprint::Fingerprint; -use crate::stable_hasher; -#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable_NoContext, Decodable_NoContext, Hash)] +#[derive( + Copy, + Clone, + PartialEq, + Eq, + Debug, + Encodable_NoContext, + Decodable_NoContext, + Hash, + HashStable_NoContext +)] pub struct Svh { hash: Fingerprint, } @@ -39,11 +48,3 @@ impl fmt::Display for Svh { f.pad(&self.to_hex()) } } - -impl stable_hasher::HashStable for Svh { - #[inline] - fn hash_stable(&self, ctx: &mut T, hasher: &mut stable_hasher::StableHasher) { - let Svh { hash } = *self; - hash.hash_stable(ctx, hasher); - } -} diff --git a/compiler/rustc_hir/src/diagnostic_items.rs b/compiler/rustc_hir/src/diagnostic_items.rs index 67e9c9eeedc43..5e0915de9d388 100644 --- a/compiler/rustc_hir/src/diagnostic_items.rs +++ b/compiler/rustc_hir/src/diagnostic_items.rs @@ -1,19 +1,13 @@ use rustc_data_structures::fx::FxIndexMap; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use rustc_span::def_id::DefIdMap; use crate::def_id::DefId; -#[derive(Debug, Default)] +#[derive(Debug, Default, HashStable_Generic)] pub struct DiagnosticItems { + #[stable_hasher(ignore)] pub id_to_name: DefIdMap, pub name_to_id: FxIndexMap, } - -impl HashStable for DiagnosticItems { - #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.name_to_id.hash_stable(ctx, hasher); - } -} diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index a3430230b1c87..d7f75e08bac82 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -64,7 +64,7 @@ decl_derive!( hash_stable::hash_stable_generic_derive ); decl_derive!( - [HashStable_NoContext] => + [HashStable_NoContext, attributes(stable_hasher)] => /// `HashStable` implementation that has no `HashStableContext` bound and /// which adds `where` bounds for `HashStable` based off of fields and not /// generics. This is suitable for use in crates like `rustc_type_ir`. diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 1ffbdfbf11875..1cfff3f2aa168 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -54,7 +54,7 @@ use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}; use rustc_hir::def_id::DefId; use rustc_hir::definitions::DefPathHash; -use rustc_macros::{Decodable, Encodable}; +use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_span::Symbol; use super::{KeyFingerprintStyle, SerializedDepNodeIndex}; @@ -290,7 +290,9 @@ pub struct DepKindVTable<'tcx> { /// some independent path or string that persists between runs without /// the need to be mapped or unmapped. (This ensures we can serialize /// them even in the absence of a tcx.) -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +#[derive( + Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, HashStable +)] pub struct WorkProductId { hash: Fingerprint, } @@ -302,13 +304,6 @@ impl WorkProductId { WorkProductId { hash: hasher.finish() } } } - -impl HashStable for WorkProductId { - #[inline] - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - self.hash.hash_stable(hcx, hasher) - } -} impl ToStableHashKey for WorkProductId { type KeyType = Fingerprint; #[inline] diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9d0e4b5e6dfa6..8ac532ff4863d 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -891,7 +891,7 @@ pub struct VarBindingForm<'tcx> { pub introductions: Vec, } -#[derive(Clone, Debug, TyEncodable, TyDecodable)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub enum BindingForm<'tcx> { /// This is a binding for a non-`self` binding, or a `self` that has an explicit type. Var(VarBindingForm<'tcx>), @@ -909,25 +909,6 @@ pub struct VarBindingIntroduction { pub is_shorthand: bool, } -mod binding_form_impl { - use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; - - use crate::ich::StableHashingContext; - - impl<'a, 'tcx> HashStable> for super::BindingForm<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use super::BindingForm::*; - std::mem::discriminant(self).hash_stable(hcx, hasher); - - match self { - Var(binding) => binding.hash_stable(hcx, hasher), - ImplicitSelf(kind) => kind.hash_stable(hcx, hasher), - RefForGuard(local) => local.hash_stable(hcx, hasher), - } - } - } -} - /// `BlockTailInfo` is attached to the `LocalDecl` for temporaries /// created during evaluation of expressions in a block tail /// expression; that is, a block like `{ STMT_1; STMT_2; EXPR }`. diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index dea077ce30cc3..3fe944af94230 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -2653,7 +2653,7 @@ impl_pos! { pub struct BytePos(pub u32); /// A byte offset relative to file beginning. - #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] + #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, HashStable_Generic)] pub struct RelativeBytePos(pub u32); /// A character offset. @@ -2677,12 +2677,6 @@ impl Decodable for BytePos { } } -impl HashStable for RelativeBytePos { - fn hash_stable(&self, hcx: &mut H, hasher: &mut StableHasher) { - self.0.hash_stable(hcx, hasher); - } -} - impl Encodable for RelativeBytePos { fn encode(&self, s: &mut S) { s.emit_u32(self.0); diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index f179274846488..c3de7e257662f 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -2,7 +2,7 @@ //! Note that these are similar to but not always identical to LLVM's feature names, //! and Rust adds some features that do not correspond to LLVM features at all. use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_macros::HashStable_Generic; use rustc_span::{Symbol, sym}; use crate::spec::{Abi, Arch, FloatAbi, RustcAbi, Target}; @@ -12,7 +12,7 @@ use crate::spec::{Abi, Arch, FloatAbi, RustcAbi, Target}; pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"]; /// Stability information for target features. -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, HashStable_Generic)] pub enum Stability { /// This target feature is stable, it can be used in `#[target_feature]` and /// `#[cfg(target_feature)]`. @@ -32,22 +32,6 @@ pub enum Stability { } use Stability::*; -impl HashStable for Stability { - #[inline] - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - std::mem::discriminant(self).hash_stable(hcx, hasher); - match self { - Stability::Stable => {} - Stability::Unstable(nightly_feature) => { - nightly_feature.hash_stable(hcx, hasher); - } - Stability::Forbidden { reason } => { - reason.hash_stable(hcx, hasher); - } - } - } -} - impl Stability { /// Returns whether the feature can be used in `cfg(target_feature)` ever. /// (It might still be nightly-only even if this returns `true`, so make sure to also check From 9f7d502d64d52cae1dd21ebd0a309c8aead3dbba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 6 Feb 2026 14:58:01 +0100 Subject: [PATCH 09/10] Remove deterministic picking from query cycle handling --- Cargo.lock | 1 - compiler/rustc_middle/src/query/stack.rs | 8 +-- compiler/rustc_query_impl/Cargo.toml | 1 - compiler/rustc_query_impl/src/job.rs | 71 +++++++++-------------- compiler/rustc_query_impl/src/plumbing.rs | 11 +--- 5 files changed, 31 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cfed18eee113c..b00b9c55b7595 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4492,7 +4492,6 @@ dependencies = [ "rustc_abi", "rustc_data_structures", "rustc_errors", - "rustc_hashes", "rustc_hir", "rustc_index", "rustc_macros", diff --git a/compiler/rustc_middle/src/query/stack.rs b/compiler/rustc_middle/src/query/stack.rs index b2b01517b7ee6..fd80c7edd602d 100644 --- a/compiler/rustc_middle/src/query/stack.rs +++ b/compiler/rustc_middle/src/query/stack.rs @@ -4,7 +4,6 @@ use std::mem::transmute; use std::sync::Arc; use rustc_data_structures::sync::{DynSend, DynSync}; -use rustc_hashes::Hash64; use rustc_hir::def::DefKind; use rustc_span::Span; use rustc_span::def_id::DefId; @@ -23,9 +22,6 @@ pub struct QueryStackFrame { pub info: I, pub dep_kind: DepKind, - /// This hash is used to deterministically pick - /// a query to remove cycles in the parallel compiler. - pub hash: Hash64, pub def_id: Option, /// A def-id that is extracted from a `Ty` in a query key pub def_id_for_ty_in_cycle: Option, @@ -36,18 +32,16 @@ impl<'tcx> QueryStackFrame> { pub fn new( info: QueryStackDeferred<'tcx>, dep_kind: DepKind, - hash: Hash64, def_id: Option, def_id_for_ty_in_cycle: Option, ) -> Self { - Self { info, def_id, dep_kind, hash, def_id_for_ty_in_cycle } + Self { info, def_id, dep_kind, def_id_for_ty_in_cycle } } pub fn lift(&self) -> QueryStackFrame { QueryStackFrame { info: self.info.extract(), dep_kind: self.dep_kind, - hash: self.hash, def_id: self.def_id, def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle, } diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 5b840cba5a59e..449d2ed5334a8 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -9,7 +9,6 @@ measureme = "12.0.1" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_query_impl/src/job.rs b/compiler/rustc_query_impl/src/job.rs index 5f728fec83c3b..2d9824a783ea5 100644 --- a/compiler/rustc_query_impl/src/job.rs +++ b/compiler/rustc_query_impl/src/job.rs @@ -209,27 +209,6 @@ fn connected_to_root<'tcx>( visit_waiters(job_map, query, |_, successor| connected_to_root(job_map, successor, visited)) } -// Deterministically pick an query from a list -fn pick_query<'a, 'tcx, T, F>(job_map: &QueryJobMap<'tcx>, queries: &'a [T], f: F) -> &'a T -where - F: Fn(&T) -> (Span, QueryJobId), -{ - // Deterministically pick an entry point - // FIXME: Sort this instead - queries - .iter() - .min_by_key(|v| { - let (span, query) = f(v); - let hash = job_map.frame_of(query).hash; - // Prefer entry points which have valid spans for nicer error messages - // We add an integer to the tuple ensuring that entry points - // with valid spans are picked first - let span_cmp = if span == DUMMY_SP { 1 } else { 0 }; - (span_cmp, hash) - }) - .unwrap() -} - /// Looks for query cycles starting from the last query in `jobs`. /// If a cycle is found, all queries in the cycle is removed from `jobs` and /// the function return true. @@ -263,48 +242,56 @@ fn remove_cycle<'tcx>( } } + struct EntryPoint { + query_in_cycle: QueryJobId, + waiter: Option<(Span, QueryJobId)>, + } + // Find the queries in the cycle which are // connected to queries outside the cycle let entry_points = stack .iter() - .filter_map(|&(span, query)| { - if job_map.parent_of(query).is_none() { + .filter_map(|&(_, query_in_cycle)| { + if job_map.parent_of(query_in_cycle).is_none() { // This query is connected to the root (it has no query parent) - Some((span, query, None)) + Some(EntryPoint { query_in_cycle, waiter: None }) } else { - let mut waiters = Vec::new(); - // Find all the direct waiters who lead to the root - let _ = visit_waiters(job_map, query, |span, waiter| { + let mut waiter_on_cycle = None; + // Find a direct waiter who leads to the root + let _ = visit_waiters(job_map, query_in_cycle, |span, waiter| { // Mark all the other queries in the cycle as already visited let mut visited = FxHashSet::from_iter(stack.iter().map(|q| q.1)); if connected_to_root(job_map, waiter, &mut visited).is_break() { - waiters.push((span, waiter)); + waiter_on_cycle = Some((span, waiter)); + ControlFlow::Break(None) + } else { + ControlFlow::Continue(()) } - - ControlFlow::Continue(()) }); - if waiters.is_empty() { - None - } else { - // Deterministically pick one of the waiters to show to the user - let waiter = *pick_query(job_map, &waiters, |s| *s); - Some((span, query, Some(waiter))) - } + + waiter_on_cycle.map(|waiter_on_cycle| EntryPoint { + query_in_cycle, + waiter: Some(waiter_on_cycle), + }) } }) - .collect::)>>(); + .collect::>(); - // Deterministically pick an entry point - let (_, entry_point, usage) = pick_query(job_map, &entry_points, |e| (e.0, e.1)); + // Pick an entry point, preferring ones with waiters + let entry_point = entry_points + .iter() + .find(|entry_point| entry_point.waiter.is_some()) + .unwrap_or(&entry_points[0]); // Shift the stack so that our entry point is first - let entry_point_pos = stack.iter().position(|(_, query)| query == entry_point); + let entry_point_pos = + stack.iter().position(|(_, query)| *query == entry_point.query_in_cycle); if let Some(pos) = entry_point_pos { stack.rotate_left(pos); } - let usage = usage.map(|(span, job)| (span, job_map.frame_of(job).clone())); + let usage = entry_point.waiter.map(|(span, job)| (span, job_map.frame_of(job).clone())); // Create the cycle error let error = CycleError { diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 31e81a62d5270..a9153cbc90df4 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -4,10 +4,8 @@ use std::num::NonZero; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_data_structures::unord::UnordMap; -use rustc_hashes::Hash64; use rustc_hir::def_id::DefId; use rustc_hir::limit::Limit; use rustc_index::Idx; @@ -319,18 +317,11 @@ where { let kind = vtable.dep_kind; - let hash = tcx.with_stable_hashing_context(|mut hcx| { - let mut hasher = StableHasher::new(); - kind.as_usize().hash_stable(&mut hcx, &mut hasher); - key.hash_stable(&mut hcx, &mut hasher); - hasher.finish::() - }); - let def_id: Option = key.key_as_def_id(); let def_id_for_ty_in_cycle: Option = key.def_id_for_ty_in_cycle(); let info = QueryStackDeferred::new((tcx, vtable, key), mk_query_stack_frame_extra); - QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle) + QueryStackFrame::new(info, kind, def_id, def_id_for_ty_in_cycle) } pub(crate) fn encode_query_results<'a, 'tcx, Q, C: QueryCache, const FLAGS: QueryFlags>( From 1f076d2f938b42fe968ff06f1107871a665eabe9 Mon Sep 17 00:00:00 2001 From: BitSyndicate1 <100071875+BitSyndicate1@users.noreply.github.com> Date: Mon, 23 Feb 2026 01:20:41 +0000 Subject: [PATCH 10/10] Add try_shrink_to and try_shrink_to_fit to Vec * Add try_shrink_to and try_shrink_to_fit to Vec Both functions are required to support shrinking a vector in environments without global OOM handling. * Format the try_shrink functions * Remove excess "```" from doc * Remove `cfg(not(no_global_oom_handling))` from rawvecinner::shrink * Fix import cmp even if no_global_oom_handling is defined --- library/alloc/src/raw_vec/mod.rs | 31 +++++++++++++- library/alloc/src/vec/mod.rs | 71 ++++++++++++++++++++++++++++++-- 2 files changed, 97 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index ff996ba93cd7f..27a41369d4e5e 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -399,6 +399,21 @@ impl RawVec { // SAFETY: All calls on self.inner pass T::LAYOUT as the elem_layout unsafe { self.inner.shrink_to_fit(cap, T::LAYOUT) } } + + /// Shrinks the buffer down to the specified capacity. If the given amount + /// is 0, actually completely deallocates. + /// + /// # Errors + /// + /// This function returns an error if the allocator cannot shrink the allocation. + /// + /// # Panics + /// + /// Panics if the given amount is *larger* than the current capacity. + #[inline] + pub(crate) fn try_shrink_to_fit(&mut self, cap: usize) -> Result<(), TryReserveError> { + unsafe { self.inner.try_shrink_to_fit(cap, T::LAYOUT) } + } } unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { @@ -731,6 +746,20 @@ impl RawVecInner { } } + /// # Safety + /// + /// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to + /// initially construct `self` + /// - `elem_layout`'s size must be a multiple of its alignment + /// - `cap` must be less than or equal to `self.capacity(elem_layout.size())` + unsafe fn try_shrink_to_fit( + &mut self, + cap: usize, + elem_layout: Layout, + ) -> Result<(), TryReserveError> { + unsafe { self.shrink(cap, elem_layout) } + } + #[inline] const fn needs_to_grow(&self, len: usize, additional: usize, elem_layout: Layout) -> bool { additional > self.capacity(elem_layout.size()).wrapping_sub(len) @@ -778,7 +807,6 @@ impl RawVecInner { /// initially construct `self` /// - `elem_layout`'s size must be a multiple of its alignment /// - `cap` must be less than or equal to `self.capacity(elem_layout.size())` - #[cfg(not(no_global_oom_handling))] #[inline] unsafe fn shrink(&mut self, cap: usize, elem_layout: Layout) -> Result<(), TryReserveError> { assert!(cap <= self.capacity(elem_layout.size()), "Tried to shrink to a larger capacity"); @@ -796,7 +824,6 @@ impl RawVecInner { /// /// # Safety /// `cap <= self.capacity()` - #[cfg(not(no_global_oom_handling))] unsafe fn shrink_unchecked( &mut self, cap: usize, diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 6cbe89d9da4f2..a196489bfb341 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -75,8 +75,6 @@ #[cfg(not(no_global_oom_handling))] use core::clone::TrivialClone; -#[cfg(not(no_global_oom_handling))] -use core::cmp; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; #[cfg(not(no_global_oom_handling))] @@ -88,7 +86,7 @@ use core::mem::{self, Assume, ManuallyDrop, MaybeUninit, SizedTypeProperties, Tr use core::ops::{self, Index, IndexMut, Range, RangeBounds}; use core::ptr::{self, NonNull}; use core::slice::{self, SliceIndex}; -use core::{fmt, hint, intrinsics, ub_checks}; +use core::{cmp, fmt, hint, intrinsics, ub_checks}; #[stable(feature = "extract_if", since = "1.87.0")] pub use self::extract_if::ExtractIf; @@ -1613,6 +1611,73 @@ impl Vec { } } + /// Tries to shrink the capacity of the vector as much as possible + /// + /// The behavior of this method depends on the allocator, which may either shrink the vector + /// in-place or reallocate. The resulting vector might still have some excess capacity, just as + /// is the case for [`with_capacity`]. See [`Allocator::shrink`] for more details. + /// + /// [`with_capacity`]: Vec::with_capacity + /// + /// # Errors + /// + /// This function returns an error if the allocator fails to shrink the allocation, + /// the vector thereafter is still safe to use, the capacity remains unchanged + /// however. See [`Allocator::shrink`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_fallible_shrink)] + /// + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3]); + /// assert!(vec.capacity() >= 10); + /// vec.try_shrink_to_fit().expect("why is the test harness failing to shrink to 12 bytes"); + /// assert!(vec.capacity() >= 3); + /// ``` + #[unstable(feature = "vec_fallible_shrink", issue = "152350")] + #[inline] + pub fn try_shrink_to_fit(&mut self) -> Result<(), TryReserveError> { + if self.capacity() > self.len { self.buf.try_shrink_to_fit(self.len) } else { Ok(()) } + } + + /// Shrinks the capacity of the vector with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// If the current capacity is less than the lower limit, this is a no-op. + /// + /// # Errors + /// + /// This function returns an error if the allocator fails to shrink the allocation, + /// the vector thereafter is still safe to use, the capacity remains unchanged + /// however. See [`Allocator::shrink`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_fallible_shrink)] + /// + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3]); + /// assert!(vec.capacity() >= 10); + /// vec.try_shrink_to(4).expect("why is the test harness failing to shrink to 12 bytes"); + /// assert!(vec.capacity() >= 4); + /// vec.try_shrink_to(0).expect("this is a no-op and thus the allocator isn't involved."); + /// assert!(vec.capacity() >= 3); + /// ``` + #[unstable(feature = "vec_fallible_shrink", issue = "152350")] + #[inline] + pub fn try_shrink_to(&mut self, min_capacity: usize) -> Result<(), TryReserveError> { + if self.capacity() > min_capacity { + self.buf.try_shrink_to_fit(cmp::max(self.len, min_capacity)) + } else { + Ok(()) + } + } + /// Converts the vector into [`Box<[T]>`][owned slice]. /// /// Before doing the conversion, this method discards excess capacity like [`shrink_to_fit`].