Skip to content

Commit 35ffff2

Browse files
committed
Auto merge of rust-lang#140748 - m-ou-se:super-format-args3, r=jdonszelmann
Allow storing `format_args!()` in variable Fixes rust-lang#92698 Tracking issue for super let: rust-lang#139076 Tracking issue for format_args: rust-lang#99012 This change allows: ```rust let name = "world"; let f = format_args!("hello {name}!"); // New: Store format_args!() for later! println!("{f}"); ``` This will need an FCP. This implementation makes use of `super let`, which is unstable and might not exist in the future in its current form. However, it is entirely reasonable to assume future Rust will always have _a_ way of expressing temporary lifetimes like this, since the (stable) `pin!()` macro needs this too. (This was also the motivation for merging rust-lang#139114.) (This is a second version of rust-lang#139135)
2 parents 94de0a8 + 6786f22 commit 35ffff2

File tree

2 files changed

+17
-36
lines changed

2 files changed

+17
-36
lines changed

core/src/fmt/rt.rs

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -183,38 +183,6 @@ impl Argument<'_> {
183183
ArgumentType::Placeholder { .. } => None,
184184
}
185185
}
186-
187-
/// Used by `format_args` when all arguments are gone after inlining,
188-
/// when using `&[]` would incorrectly allow for a bigger lifetime.
189-
///
190-
/// This fails without format argument inlining, and that shouldn't be different
191-
/// when the argument is inlined:
192-
///
193-
/// ```compile_fail,E0716
194-
/// let f = format_args!("{}", "a");
195-
/// println!("{f}");
196-
/// ```
197-
#[inline]
198-
pub const fn none() -> [Self; 0] {
199-
[]
200-
}
201-
}
202-
203-
/// This struct represents the unsafety of constructing an `Arguments`.
204-
/// It exists, rather than an unsafe function, in order to simplify the expansion
205-
/// of `format_args!(..)` and reduce the scope of the `unsafe` block.
206-
#[lang = "format_unsafe_arg"]
207-
pub struct UnsafeArg {
208-
_private: (),
209-
}
210-
211-
impl UnsafeArg {
212-
/// See documentation where `UnsafeArg` is required to know when it is safe to
213-
/// create and use `UnsafeArg`.
214-
#[inline]
215-
pub const unsafe fn new() -> Self {
216-
Self { _private: () }
217-
}
218186
}
219187

220188
/// Used by the format_args!() macro to create a fmt::Arguments object.
@@ -248,8 +216,7 @@ impl<'a> Arguments<'a> {
248216

249217
/// Specifies nonstandard formatting parameters.
250218
///
251-
/// An `rt::UnsafeArg` is required because the following invariants must be held
252-
/// in order for this function to be safe:
219+
/// SAFETY: the following invariants must be held:
253220
/// 1. The `pieces` slice must be at least as long as `fmt`.
254221
/// 2. Every `rt::Placeholder::position` value within `fmt` must be a valid index of `args`.
255222
/// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`.
@@ -261,11 +228,10 @@ impl<'a> Arguments<'a> {
261228
/// const _: () = if false { panic!("a {:1}", "a") };
262229
/// ```
263230
#[inline]
264-
pub fn new_v1_formatted(
231+
pub unsafe fn new_v1_formatted(
265232
pieces: &'a [&'static str],
266233
args: &'a [rt::Argument<'a>],
267234
fmt: &'a [rt::Placeholder],
268-
_unsafe_arg: rt::UnsafeArg,
269235
) -> Arguments<'a> {
270236
Arguments { pieces, fmt: Some(fmt), args }
271237
}

coretests/tests/fmt/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@ mod builders;
22
mod float;
33
mod num;
44

5+
#[test]
6+
fn test_lifetime() {
7+
// Trigger all different forms of expansion,
8+
// and check that each of them can be stored as a variable.
9+
let a = format_args!("hello");
10+
let a = format_args!("hello {a}");
11+
let a = format_args!("hello {a:1}");
12+
let a = format_args!("hello {a} {a:?}");
13+
assert_eq!(a.to_string(), "hello hello hello hello hello hello hello");
14+
15+
// Without arguments, it should also work in consts.
16+
const A: std::fmt::Arguments<'static> = format_args!("hello");
17+
assert_eq!(A.to_string(), "hello");
18+
}
19+
520
#[test]
621
fn test_format_flags() {
722
// No residual flags left by pointer formatting

0 commit comments

Comments
 (0)