Stabilize format_args_capture
Works as expected, and there are widespread reports of success with it,
as well as interest in it.
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index aca7d31..76d3a83 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -3,7 +3,7 @@
#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(crate_visibility_modifier)]
-#![feature(format_args_capture)]
+#![cfg_attr(bootstrap, feature(format_args_capture))]
#![feature(in_band_lifetimes)]
#![feature(iter_zip)]
#![feature(let_else)]
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 52b00a2..097eadd 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -527,17 +527,9 @@ fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
self.verify_arg_type(Exact(idx), ty)
}
None => {
- let capture_feature_enabled = self
- .ecx
- .ecfg
- .features
- .map_or(false, |features| features.format_args_capture);
-
// For the moment capturing variables from format strings expanded from macros is
// disabled (see RFC #2795)
- let can_capture = capture_feature_enabled && self.is_literal;
-
- if can_capture {
+ if self.is_literal {
// Treat this name as a variable to capture from the surrounding scope
let idx = self.args.len();
self.arg_types.push(Vec::new());
@@ -559,23 +551,15 @@ fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
};
let mut err = self.ecx.struct_span_err(sp, &msg[..]);
- if capture_feature_enabled && !self.is_literal {
- err.note(&format!(
- "did you intend to capture a variable `{}` from \
- the surrounding scope?",
- name
- ));
- err.note(
- "to avoid ambiguity, `format_args!` cannot capture variables \
- when the format string is expanded from a macro",
- );
- } else if self.ecx.parse_sess().unstable_features.is_nightly_build() {
- err.help(&format!(
- "if you intended to capture `{}` from the surrounding scope, add \
- `#![feature(format_args_capture)]` to the crate attributes",
- name
- ));
- }
+ err.note(&format!(
+ "did you intend to capture a variable `{}` from \
+ the surrounding scope?",
+ name
+ ));
+ err.note(
+ "to avoid ambiguity, `format_args!` cannot capture variables \
+ when the format string is expanded from a macro",
+ );
err.emit();
}
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 21a2eb7..bb3d3a4 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -6,7 +6,7 @@
#![feature(crate_visibility_modifier)]
#![feature(backtrace)]
#![feature(if_let_guard)]
-#![feature(format_args_capture)]
+#![cfg_attr(bootstrap, feature(format_args_capture))]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(nll)]
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index 521ca21..4e84a9d 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -1,7 +1,7 @@
#![feature(crate_visibility_modifier)]
#![feature(decl_macro)]
#![feature(destructuring_assignment)]
-#![feature(format_args_capture)]
+#![cfg_attr(bootstrap, feature(format_args_capture))]
#![feature(if_let_guard)]
#![feature(iter_zip)]
#![feature(let_else)]
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 3bd1272..3cb543f 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -301,6 +301,8 @@ macro_rules! declare_features {
(accepted, relaxed_struct_unsize, "1.58.0", Some(81793), None),
/// Allows dereferencing raw pointers during const eval.
(accepted, const_raw_ptr_deref, "1.58.0", Some(51911), None),
+ /// Allows capturing variables in scope using format_args!
+ (accepted, format_args_capture, "1.58.0", Some(67984), None),
// -------------------------------------------------------------------------
// feature-group-end: accepted features
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index d8b4539..61dd505 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -539,9 +539,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
/// Be more precise when looking for live drops in a const context.
(active, const_precise_live_drops, "1.46.0", Some(73255), None),
- /// Allows capturing variables in scope using format_args!
- (active, format_args_capture, "1.46.0", Some(67984), None),
-
/// Allows `if let` guard in match arms.
(active, if_let_guard, "1.47.0", Some(51114), None),
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index f6514dd..507b442 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -30,7 +30,7 @@
#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(crate_visibility_modifier)]
-#![feature(format_args_capture)]
+#![cfg_attr(bootstrap, feature(format_args_capture))]
#![feature(iter_order_by)]
#![feature(iter_zip)]
#![feature(never_type)]
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 4adec3c..af1c724 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -7,7 +7,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(crate_visibility_modifier)]
#![feature(in_band_lifetimes)]
-#![feature(format_args_capture)]
+#![cfg_attr(bootstrap, feature(format_args_capture))]
#![feature(iter_zip)]
#![feature(map_try_insert)]
#![feature(min_specialization)]
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index f5bea83..d17e887 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -13,7 +13,7 @@
#![feature(drain_filter)]
#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
-#![feature(format_args_capture)]
+#![cfg_attr(bootstrap, feature(format_args_capture))]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(never_type)]
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index ba0fd12..0881cf0 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -58,7 +58,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
-#![feature(format_args_capture)]
+#![cfg_attr(bootstrap, feature(format_args_capture))]
#![feature(if_let_guard)]
#![feature(in_band_lifetimes)]
#![feature(is_sorted)]
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 746dd50..4a66c3f 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -105,7 +105,7 @@
#![feature(fmt_internals)]
#![feature(fn_traits)]
#![feature(inherent_ascii_escape)]
-#![feature(format_args_capture)]
+#![cfg_attr(bootstrap, feature(format_args_capture))]
#![feature(inplace_iteration)]
#![feature(iter_advance_by)]
#![feature(iter_zip)]
diff --git a/src/doc/unstable-book/src/library-features/format-args-capture.md b/src/doc/unstable-book/src/library-features/format-args-capture.md
deleted file mode 100644
index 64b1b3d..0000000
--- a/src/doc/unstable-book/src/library-features/format-args-capture.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# `format_args_capture`
-
-The tracking issue for this feature is: [#67984]
-
-[#67984]: https://github.com/rust-lang/rust/issues/67984
-
-------------------------
-
-Enables `format_args!` (and macros which use `format_args!` in their implementation, such
-as `format!`, `print!` and `panic!`) to capture variables from the surrounding scope.
-This avoids the need to pass named parameters when the binding in question
-already exists in scope.
-
-```rust
-#![feature(format_args_capture)]
-
-let (person, species, name) = ("Charlie Brown", "dog", "Snoopy");
-
-// captures named argument `person`
-print!("Hello {person}");
-
-// captures named arguments `species` and `name`
-format!("The {species}'s name is {name}.");
-```
-
-This also works for formatting parameters such as width and precision:
-
-```rust
-#![feature(format_args_capture)]
-
-let precision = 2;
-let s = format!("{:.precision$}", 1.324223);
-
-assert_eq!(&s, "1.32");
-```
-
-A non-exhaustive list of macros which benefit from this functionality include:
-- `format!`
-- `print!` and `println!`
-- `eprint!` and `eprintln!`
-- `write!` and `writeln!`
-- `panic!`
-- `unreachable!`
-- `unimplemented!`
-- `todo!`
-- `assert!` and similar
-- macros in many thirdparty crates, such as `log`
diff --git a/src/test/ui/fmt/feature-gate-format-args-capture.rs b/src/test/ui/fmt/feature-gate-format-args-capture.rs
deleted file mode 100644
index 21af916..0000000
--- a/src/test/ui/fmt/feature-gate-format-args-capture.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
- format!("{foo}"); //~ ERROR: there is no argument named `foo`
-
- // panic! doesn't hit format_args! unless there are two or more arguments.
- panic!("{foo} {bar}", bar=1); //~ ERROR: there is no argument named `foo`
-}
diff --git a/src/test/ui/fmt/feature-gate-format-args-capture.stderr b/src/test/ui/fmt/feature-gate-format-args-capture.stderr
deleted file mode 100644
index f08f1651..0000000
--- a/src/test/ui/fmt/feature-gate-format-args-capture.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-error: there is no argument named `foo`
- --> $DIR/feature-gate-format-args-capture.rs:2:14
- |
-LL | format!("{foo}");
- | ^^^^^
- |
- = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
-
-error: there is no argument named `foo`
- --> $DIR/feature-gate-format-args-capture.rs:5:13
- |
-LL | panic!("{foo} {bar}", bar=1);
- | ^^^^^
- |
- = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/fmt/format-args-capture-macro-hygiene.rs b/src/test/ui/fmt/format-args-capture-macro-hygiene.rs
index 6ca7dcc..fdbd938 100644
--- a/src/test/ui/fmt/format-args-capture-macro-hygiene.rs
+++ b/src/test/ui/fmt/format-args-capture-macro-hygiene.rs
@@ -1,5 +1,3 @@
-#![feature(format_args_capture)]
-
fn main() {
format!(concat!("{foo}")); //~ ERROR: there is no argument named `foo`
format!(concat!("{ba", "r} {}"), 1); //~ ERROR: there is no argument named `bar`
diff --git a/src/test/ui/fmt/format-args-capture-missing-variables.rs b/src/test/ui/fmt/format-args-capture-missing-variables.rs
index 3a4b614..46fc083 100644
--- a/src/test/ui/fmt/format-args-capture-missing-variables.rs
+++ b/src/test/ui/fmt/format-args-capture-missing-variables.rs
@@ -1,5 +1,3 @@
-#![feature(format_args_capture)]
-
fn main() {
format!("{} {foo} {} {bar} {}", 1, 2, 3);
//~^ ERROR: cannot find value `foo` in this scope
diff --git a/src/test/ui/fmt/format-args-capture.rs b/src/test/ui/fmt/format-args-capture.rs
index b30e9a4..e830a5b 100644
--- a/src/test/ui/fmt/format-args-capture.rs
+++ b/src/test/ui/fmt/format-args-capture.rs
@@ -1,5 +1,4 @@
// run-pass
-#![feature(format_args_capture)]
#![feature(cfg_panic)]
fn main() {
diff --git a/src/test/ui/fmt/ifmt-bad-arg.stderr b/src/test/ui/fmt/ifmt-bad-arg.stderr
index f4c84e2..a6c7aa3 100644
--- a/src/test/ui/fmt/ifmt-bad-arg.stderr
+++ b/src/test/ui/fmt/ifmt-bad-arg.stderr
@@ -64,7 +64,6 @@
LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
| ^^^^^
|
- = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
error: there is no argument named `bar`
--> $DIR/ifmt-bad-arg.rs:27:26
@@ -72,7 +71,6 @@
LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
| ^^^^^
|
- = help: if you intended to capture `bar` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
error: there is no argument named `foo`
--> $DIR/ifmt-bad-arg.rs:31:14
@@ -80,7 +78,6 @@
LL | format!("{foo}");
| ^^^^^
|
- = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
error: multiple unused formatting arguments
--> $DIR/ifmt-bad-arg.rs:32:17
@@ -162,7 +159,6 @@
LL | format!("{valuea} {valueb}", valuea=5, valuec=7);
| ^^^^^^^^
|
- = help: if you intended to capture `valueb` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
error: named argument never used
--> $DIR/ifmt-bad-arg.rs:45:51
@@ -214,7 +210,6 @@
LL | {foo}
| ^^^^^
|
- = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
error: invalid format string: expected `'}'`, found `'t'`
--> $DIR/ifmt-bad-arg.rs:75:1