From 06e4ff4d61f44d7e239e02256829ecf1e5598657 Mon Sep 17 00:00:00 2001
From: Jon Gjengset <jon@thesquareplanet.com>
Date: Fri, 27 Sep 2019 17:15:17 -0400
Subject: [PATCH 1/3] 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/rust#64477 for details.
---
 src/liballoc/macros.rs         |  5 ++++-
 src/test/ui/fmt/issue-64477.rs | 16 ++++++++++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)
 create mode 100644 src/test/ui/fmt/issue-64477.rs

diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs
index 2f2cdc39c633d..422d3486f92b2 100644
--- a/src/liballoc/macros.rs
+++ b/src/liballoc/macros.rs
@@ -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
+    }}
 }
diff --git a/src/test/ui/fmt/issue-64477.rs b/src/test/ui/fmt/issue-64477.rs
new file mode 100644
index 0000000000000..b7c8cf17c3148
--- /dev/null
+++ b/src/test/ui/fmt/issue-64477.rs
@@ -0,0 +1,16 @@
+// 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.
+async fn foo(_: String) {}
+
+fn bar() -> impl Send {
+    async move {
+        foo(format!("{}:{}", 1, 2)).await;
+    }
+}
+
+fn main() {
+    let _ = bar();
+}

From 4d34ce2c2515a429bea325b93aea332ac8d6a7b9 Mon Sep 17 00:00:00 2001
From: Jon Gjengset <jon@thesquareplanet.com>
Date: Fri, 27 Sep 2019 23:19:37 -0400
Subject: [PATCH 2/3] Place test with async-await and use 2018 edition

---
 .../issue-64477.rs => async-await/issues/issue-64477-2.rs}  | 6 ++++++
 1 file changed, 6 insertions(+)
 rename src/test/ui/{fmt/issue-64477.rs => async-await/issues/issue-64477-2.rs} (89%)

diff --git a/src/test/ui/fmt/issue-64477.rs b/src/test/ui/async-await/issues/issue-64477-2.rs
similarity index 89%
rename from src/test/ui/fmt/issue-64477.rs
rename to src/test/ui/async-await/issues/issue-64477-2.rs
index b7c8cf17c3148..2360b57cc4544 100644
--- a/src/test/ui/fmt/issue-64477.rs
+++ b/src/test/ui/async-await/issues/issue-64477-2.rs
@@ -1,8 +1,14 @@
+// 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 {

From 8990f7d627525db934831cc29d5805172d80e156 Mon Sep 17 00:00:00 2001
From: Jon Gjengset <jon@thesquareplanet.com>
Date: Sat, 28 Sep 2019 09:55:22 -0400
Subject: [PATCH 3/3] Update pretty-print test with new format! impl

---
 src/test/pretty/issue-4264.pp | 56 +++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 26 deletions(-)

diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp
index 4cf2e90e635fd..0f71dbe486b97 100644
--- a/src/test/pretty/issue-4264.pp
+++ b/src/test/pretty/issue-4264.pp
@@ -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 {