Skip to content

Commit d845e6f

Browse files
authored
Rollup merge of rust-lang#64856 - jonhoo:format-temporaries, r=sfackler
Scope format! temporaries This places the temporaries that `format!` generates to refer to its arguments (through `&dyn Trait`) in a short-lived scope surrounding just the invocation of `format!`. This enables `format!` to be used in generators without the temporaries preventing the generator from being `Send` (due to `dyn Trait` not being `Sync`). See rust-lang#64477 for details.
2 parents ad808d9 + 31fc42b commit d845e6f

File tree

3 files changed

+56
-27
lines changed

3 files changed

+56
-27
lines changed

src/liballoc/macros.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,8 @@ macro_rules! vec {
9898
#[macro_export]
9999
#[stable(feature = "rust1", since = "1.0.0")]
100100
macro_rules! format {
101-
($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*)))
101+
($($arg:tt)*) => {{
102+
let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
103+
res
104+
}}
102105
}

src/test/pretty/issue-4264.pp

+30-26
Original file line numberDiff line numberDiff line change
@@ -29,33 +29,37 @@
2929

3030

3131

32-
((::alloc::fmt::format as
33-
for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((::core::fmt::Arguments::new_v1
34-
as
35-
fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments::<'_>::new_v1})((&([("test"
36-
as
37-
&'static str)]
38-
as
39-
[&str; 1])
40-
as
41-
&[&str; 1]),
42-
(&(match (()
32+
({
33+
let res =
34+
((::alloc::fmt::format as
35+
for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((::core::fmt::Arguments::new_v1
36+
as
37+
fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments::<'_>::new_v1})((&([("test"
38+
as
39+
&'static str)]
40+
as
41+
[&str; 1])
4342
as
44-
())
45-
{
46-
()
47-
=>
48-
([]
49-
as
50-
[std::fmt::ArgumentV1<'_>; 0]),
51-
}
52-
as
53-
[std::fmt::ArgumentV1<'_>; 0])
54-
as
55-
&[std::fmt::ArgumentV1<'_>; 0]))
56-
as
57-
std::fmt::Arguments<'_>))
58-
as std::string::String);
43+
&[&str; 1]),
44+
(&(match (()
45+
as
46+
())
47+
{
48+
()
49+
=>
50+
([]
51+
as
52+
[std::fmt::ArgumentV1<'_>; 0]),
53+
}
54+
as
55+
[std::fmt::ArgumentV1<'_>; 0])
56+
as
57+
&[std::fmt::ArgumentV1<'_>; 0]))
58+
as
59+
std::fmt::Arguments<'_>))
60+
as std::string::String);
61+
(res as std::string::String)
62+
} as std::string::String);
5963
} as ())
6064
pub type Foo = [i32; (3 as usize)];
6165
pub struct Bar {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Another regression test for #64477.
2+
//
3+
// In the past, the code generated by `format!` produced temporaries in the surrounding scope that
4+
// borrowed the arguments through `&dyn Trait`. These temporaries do not implement `Send`, which
5+
// meant that when `format!` was used in an async block, the resulting generator was not `Send`.
6+
// See https://github.com/rust-lang/rust/issues/64477#issuecomment-534669068 for details
7+
// and https://github.com/rust-lang/rust/issues/64477#issuecomment-531882958 for an example.
8+
//
9+
// check-pass
10+
// edition:2018
11+
12+
async fn foo(_: String) {}
13+
14+
fn bar() -> impl Send {
15+
async move {
16+
foo(format!("{}:{}", 1, 2)).await;
17+
}
18+
}
19+
20+
fn main() {
21+
let _ = bar();
22+
}

0 commit comments

Comments
 (0)