Skip to content

Commit

Permalink
Rollup merge of rust-lang#64856 - jonhoo:format-temporaries, r=sfackler
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Centril authored Nov 24, 2019
2 parents ad808d9 + 31fc42b commit d845e6f
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 27 deletions.
5 changes: 4 additions & 1 deletion src/liballoc/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,8 @@ macro_rules! vec {
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! format {
($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*)))
($($arg:tt)*) => {{
let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
res
}}
}
56 changes: 30 additions & 26 deletions src/test/pretty/issue-4264.pp
Original file line number Diff line number Diff line change
Expand Up @@ -29,33 +29,37 @@



((::alloc::fmt::format as
for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((::core::fmt::Arguments::new_v1
as
fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments::<'_>::new_v1})((&([("test"
as
&'static str)]
as
[&str; 1])
as
&[&str; 1]),
(&(match (()
({
let res =
((::alloc::fmt::format as
for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((::core::fmt::Arguments::new_v1
as
fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments::<'_>::new_v1})((&([("test"
as
&'static str)]
as
[&str; 1])
as
())
{
()
=>
([]
as
[std::fmt::ArgumentV1<'_>; 0]),
}
as
[std::fmt::ArgumentV1<'_>; 0])
as
&[std::fmt::ArgumentV1<'_>; 0]))
as
std::fmt::Arguments<'_>))
as std::string::String);
&[&str; 1]),
(&(match (()
as
())
{
()
=>
([]
as
[std::fmt::ArgumentV1<'_>; 0]),
}
as
[std::fmt::ArgumentV1<'_>; 0])
as
&[std::fmt::ArgumentV1<'_>; 0]))
as
std::fmt::Arguments<'_>))
as std::string::String);
(res as std::string::String)
} as std::string::String);
} as ())
pub type Foo = [i32; (3 as usize)];
pub struct Bar {
Expand Down
22 changes: 22 additions & 0 deletions src/test/ui/async-await/issues/issue-64477-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Another regression test for #64477.
//
// In the past, the code generated by `format!` produced temporaries in the surrounding scope that
// borrowed the arguments through `&dyn Trait`. These temporaries do not implement `Send`, which
// meant that when `format!` was used in an async block, the resulting generator was not `Send`.
// See https://github.com/rust-lang/rust/issues/64477#issuecomment-534669068 for details
// and https://github.com/rust-lang/rust/issues/64477#issuecomment-531882958 for an example.
//
// check-pass
// edition:2018

async fn foo(_: String) {}

fn bar() -> impl Send {
async move {
foo(format!("{}:{}", 1, 2)).await;
}
}

fn main() {
let _ = bar();
}

0 comments on commit d845e6f

Please sign in to comment.