From d778835b808daa85fa58a9bbd50e7fe624507fab Mon Sep 17 00:00:00 2001 From: Noa Date: Wed, 23 Sep 2026 13:36:42 -0500 Subject: [PATCH 1/4] Stabilize `debug_closure_helpers` --- compiler/rustc_middle/src/lib.rs | 2 +- compiler/rustc_parse/src/lib.rs | 2 +- library/core/src/fmt/builders.rs | 12 ++++++------ library/coretests/tests/lib.rs | 1 - 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 5acf9e150bb5c..ffa41454de908 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -28,6 +28,7 @@ #![allow(internal_features)] #![allow(rustc::direct_use_of_rustc_type_ir)] #![cfg_attr(bootstrap, feature(allocator_api))] +#![cfg_attr(bootstrap, feature(debug_closure_helpers))] #![cfg_attr(bootstrap, feature(never_type))] #![cfg_attr(doc, feature(intra_doc_pointers))] #![cfg_attr(not(bootstrap), feature(allocator_ext))] @@ -36,7 +37,6 @@ #![feature(const_default)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] -#![feature(debug_closure_helpers)] #![feature(decl_macro)] #![feature(default_field_values)] #![feature(deref_patterns)] diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 8a73215351aea..edd280743e437 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -1,8 +1,8 @@ //! The main parser interface. // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(debug_closure_helpers))] #![cfg_attr(test, feature(iter_order_by))] -#![feature(debug_closure_helpers)] #![feature(default_field_values)] #![feature(deref_patterns)] #![feature(iter_intersperse)] diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 6a44f9ef5374e..5094f83e2b3c2 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -211,7 +211,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// r#"Bar { bar: 0x0000000a, another: "Hello World" }"#, /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] pub fn field_with(&mut self, name: &str, value_fmt: F) -> &mut Self where F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, @@ -429,7 +429,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// r#"Foo(0x0000000a, "Hello World")"#, /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] pub fn field_with(&mut self, value_fmt: F) -> &mut Self where F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, @@ -660,7 +660,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// "{[10, 11], {12, 13}}", /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self where F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, @@ -877,7 +877,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// "[[10, 11], {12, 13}]", /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self where F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, @@ -1163,7 +1163,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// r#"{entry A: 0x0000000a, entry B: 0x0000000b}"#, /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] pub fn key_with(&mut self, key_fmt: F) -> &mut Self where F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, @@ -1256,7 +1256,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// r#"{entry A: 0x0000000a, entry B: 0x0000000b}"#, /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] pub fn value_with(&mut self, value_fmt: F) -> &mut Self where F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 69bc6edd1b833..e4906956437f0 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -47,7 +47,6 @@ #![feature(core_private_bignum)] #![feature(core_private_diy_float)] #![feature(cstr_display)] -#![feature(debug_closure_helpers)] #![feature(dec2flt)] #![feature(duration_constants)] #![feature(duration_constructors)] From 38fed83fe4b2a3691905fb4aaf30f2b9efc0f6ad Mon Sep 17 00:00:00 2001 From: Noa Date: Wed, 23 Sep 2026 14:12:14 -0500 Subject: [PATCH 2/4] Replace type parameters with APIT --- library/core/src/fmt/builders.rs | 57 ++++++++++++++++---------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 5094f83e2b3c2..8bcfb279c867f 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -212,10 +212,11 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] - pub fn field_with(&mut self, name: &str, value_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + pub fn field_with( + &mut self, + name: &str, + value_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.field(name, &DebugOnce(Cell::new(Some(value_fmt)))) } @@ -430,10 +431,11 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] - pub fn field_with(&mut self, value_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + pub fn field_with( + &mut self, + value_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self +where { self.field(&DebugOnce(Cell::new(Some(value_fmt)))) } @@ -552,10 +554,7 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { self.has_fields = true; } - fn entry_with(&mut self, entry_fmt: F) - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + fn entry_with(&mut self, entry_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result) { self.entry(&DebugOnce(Cell::new(Some(entry_fmt)))); } @@ -661,10 +660,11 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] - pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + pub fn entry_with( + &mut self, + entry_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self +where { self.inner.entry_with(entry_fmt); self } @@ -878,10 +878,11 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] - pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + pub fn entry_with( + &mut self, + entry_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self +where { self.inner.entry_with(entry_fmt); self } @@ -1164,10 +1165,10 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] - pub fn key_with(&mut self, key_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + pub fn key_with( + &mut self, + key_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.key(&DebugOnce(Cell::new(Some(key_fmt)))) } @@ -1257,10 +1258,10 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] - pub fn value_with(&mut self, value_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + pub fn value_with( + &mut self, + value_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.value(&DebugOnce(Cell::new(Some(value_fmt)))) } From 741f36a1fbc9359147b396d6b7bb3242a07b866d Mon Sep 17 00:00:00 2001 From: Noa Date: Wed, 23 Sep 2026 14:45:13 -0500 Subject: [PATCH 3/4] Remove feature attribute from doctests --- library/core/src/fmt/builders.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 8bcfb279c867f..5327341540eb0 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -187,8 +187,6 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Bar { @@ -409,8 +407,6 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(i32, String); @@ -638,8 +634,6 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(Vec, Vec); @@ -856,8 +850,6 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(Vec, Vec); @@ -1140,8 +1132,6 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(Vec<(String, i32)>); @@ -1233,8 +1223,6 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(Vec<(String, i32)>); From 87e9d79a45c70267230fb92a459a579c4eab843f Mon Sep 17 00:00:00 2001 From: Noa Date: Wed, 23 Sep 2026 14:49:21 -0500 Subject: [PATCH 4/4] Document panics --- library/core/src/fmt/builders.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 5327341540eb0..b629dd0ebe26c 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -1068,8 +1068,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// # Panics /// - /// `key` must be called before `value` and each call to `key` must be followed - /// by a corresponding call to `value`. Otherwise this method will panic. + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. /// /// # Examples /// @@ -1129,6 +1130,12 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// This method is equivalent to [`DebugMap::key`], but formats the /// key using a provided closure rather than by calling [`Debug::fmt`]. /// + /// # Panics + /// + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. + /// /// # Examples /// /// ``` @@ -1170,8 +1177,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// # Panics /// - /// `key` must be called before `value` and each call to `key` must be followed - /// by a corresponding call to `value`. Otherwise this method will panic. + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. /// /// # Examples /// @@ -1220,6 +1228,12 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// This method is equivalent to [`DebugMap::value`], but formats the /// value using a provided closure rather than by calling [`Debug::fmt`]. /// + /// # Panics + /// + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. + /// /// # Examples /// /// ``` @@ -1348,8 +1362,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// # Panics /// - /// `key` must be called before `value` and each call to `key` must be followed - /// by a corresponding call to `value`. Otherwise this method will panic. + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. /// /// # Examples ///