diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs
index 8022d1f0c7315..5c5d495466cda 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/conflict_errors.rs
@@ -595,12 +595,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     ) -> (String, String, String, String) {
         // Define a small closure that we can use to check if the type of a place
         // is a union.
-        let is_union = |place: &Place<'tcx>| -> bool {
-            place.ty(self.mir, self.infcx.tcx).ty
-                .ty_adt_def()
-                .map(|adt| adt.is_union())
-                .unwrap_or(false)
+        let union_ty = |place: &Place<'tcx>| -> Option<Ty<'tcx>> {
+            let ty = place.ty(self.mir, self.infcx.tcx).ty;
+            ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty)
         };
+        let describe_place = |place| self.describe_place(place).unwrap_or_else(|| "_".to_owned());
 
         // Start with an empty tuple, so we can use the functions on `Option` to reduce some
         // code duplication (particularly around returning an empty description in the failure
@@ -619,7 +618,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 let mut current = first_borrowed_place;
                 while let Place::Projection(box Projection { base, elem }) = current {
                     match elem {
-                        ProjectionElem::Field(field, _) if is_union(base) => {
+                        ProjectionElem::Field(field, _) if union_ty(base).is_some() => {
                             return Some((base, field));
                         },
                         _ => current = base,
@@ -632,34 +631,32 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 // borrowed place and look for a access to a different field of the same union.
                 let mut current = second_borrowed_place;
                 while let Place::Projection(box Projection { base, elem }) = current {
-                    match elem {
-                        ProjectionElem::Field(field, _) if {
-                            is_union(base) && field != target_field && base == target_base
-                        } => {
-                            let desc_base = self.describe_place(base)
-                                .unwrap_or_else(|| "_".to_owned());
-                            let desc_first = self.describe_place(first_borrowed_place)
-                                .unwrap_or_else(|| "_".to_owned());
-                            let desc_second = self.describe_place(second_borrowed_place)
-                                .unwrap_or_else(|| "_".to_owned());
-
-                            // Also compute the name of the union type, eg. `Foo` so we
-                            // can add a helpful note with it.
-                            let ty = base.ty(self.mir, self.infcx.tcx).ty;
-
-                            return Some((desc_base, desc_first, desc_second, ty.to_string()));
-                        },
-                        _ => current = base,
+                    if let ProjectionElem::Field(field, _) = elem {
+                        if let Some(union_ty) = union_ty(base) {
+                            if field != target_field && base == target_base {
+                                return Some((
+                                    describe_place(base),
+                                    describe_place(first_borrowed_place),
+                                    describe_place(second_borrowed_place),
+                                    union_ty.to_string(),
+                                ));
+                            }
+                        }
                     }
+
+                    current = base;
                 }
                 None
             })
             .unwrap_or_else(|| {
                 // If we didn't find a field access into a union, or both places match, then
                 // only return the description of the first place.
-                let desc_place = self.describe_place(first_borrowed_place)
-                    .unwrap_or_else(|| "_".to_owned());
-                (desc_place, "".to_string(), "".to_string(), "".to_string())
+                (
+                    describe_place(first_borrowed_place),
+                    "".to_string(),
+                    "".to_string(),
+                    "".to_string(),
+                )
             })
     }
 
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index a292115707d8e..7c8a3e2f68afd 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -7,7 +7,7 @@ use rustc::mir::{
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::{self, Const, DefIdTree, Ty, TyS, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
-use syntax_pos::Span;
+use syntax_pos::{Span, CompilerDesugaringKind};
 use syntax_pos::symbol::kw;
 
 use crate::dataflow::move_paths::InitLocation;
@@ -41,14 +41,19 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
         );
 
         let mut err;
-        let item_msg;
         let reason;
         let access_place_desc = self.describe_place(access_place);
         debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
 
+        let mut item_msg = match (&access_place_desc, &the_place_err) {
+            (Some(desc), _) => format!("`{}`", desc),
+            (None, Place::Base(PlaceBase::Local(local))) if self.mir.local_decls[*local]
+                .source_info.span.is_compiler_desugaring(CompilerDesugaringKind::Async)
+            => "`async fn` parameter".to_string(),
+            (None, _) => "temporary place".to_string(),
+        };
         match the_place_err {
             Place::Base(PlaceBase::Local(local)) => {
-                item_msg = format!("`{}`", access_place_desc.unwrap());
                 if let Place::Base(PlaceBase::Local(_)) = access_place {
                     reason = ", as it is not declared as mutable".to_string();
                 } else {
@@ -67,7 +72,6 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                     base.ty(self.mir, self.infcx.tcx).ty
                 ));
 
-                item_msg = format!("`{}`", access_place_desc.unwrap());
                 if self.is_upvar_field_projection(access_place).is_some() {
                     reason = ", as it is not declared as mutable".to_string();
                 } else {
@@ -82,7 +86,6 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             }) => {
                 if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
                     !self.upvars.is_empty() {
-                    item_msg = format!("`{}`", access_place_desc.unwrap());
                     debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr());
                     debug_assert!(is_closure_or_generator(
                         the_place_err.ty(self.mir, self.infcx.tcx).ty
@@ -105,7 +108,6 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                         false
                     }
                 } {
-                    item_msg = format!("`{}`", access_place_desc.unwrap());
                     reason = ", as it is immutable for the pattern guard".to_string();
                 } else {
                     let pointer_type =
@@ -114,8 +116,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                         } else {
                             "`*const` pointer"
                         };
-                    if let Some(desc) = access_place_desc {
-                        item_msg = format!("`{}`", desc);
+                    if access_place_desc.is_some() {
                         reason = match error_access {
                             AccessKind::Move |
                             AccessKind::Mutate => format!(" which is behind a {}", pointer_type),
@@ -135,10 +136,9 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
 
             Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. })) => {
                 if let Place::Base(PlaceBase::Static(_)) = access_place {
-                    item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
+                    item_msg = format!("immutable static item {}", item_msg);
                     reason = String::new();
                 } else {
-                    item_msg = format!("`{}`", access_place_desc.unwrap());
                     let static_name = &self.infcx.tcx.item_name(*def_id);
                     reason = format!(", as `{}` is an immutable static item", static_name);
                 }
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 724f8d886e8a7..c3ea9ff40a843 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -270,7 +270,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         None
     }
 
-    fn is_hir_id_from_struct_pattern_shorthand_field(&self, hir_id: hir::HirId, sp: Span) -> bool {
+    crate fn is_hir_id_from_struct_pattern_shorthand_field(
+        &self,
+        hir_id: hir::HirId,
+        sp: Span,
+    ) -> bool {
         let cm = self.sess().source_map();
         let parent_id = self.tcx.hir().get_parent_node_by_hir_id(hir_id);
         if let Some(parent) = self.tcx.hir().find_by_hir_id(parent_id) {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 8701d751f2d91..c5b85d52566d3 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -5010,6 +5010,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 Applicability::MachineApplicable,
             );
         } else if !self.check_for_cast(err, expr, found, expected) {
+            let is_struct_pat_shorthand_field = self.is_hir_id_from_struct_pattern_shorthand_field(
+                expr.hir_id,
+                expr.span,
+            );
             let methods = self.get_conversion_methods(expr.span, expected, found);
             if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {
                 let mut suggestions = iter::repeat(&expr_text).zip(methods.iter())
@@ -5019,14 +5023,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             None  // do not suggest code that is already there (#53348)
                         } else {
                             let method_call_list = [".to_vec()", ".to_string()"];
-                            if receiver.ends_with(".clone()")
+                            let sugg = if receiver.ends_with(".clone()")
                                     && method_call_list.contains(&method_call.as_str()) {
                                 let max_len = receiver.rfind(".").unwrap();
-                                Some(format!("{}{}", &receiver[..max_len], method_call))
-                            }
-                            else {
-                                Some(format!("{}{}", receiver, method_call))
-                            }
+                                format!("{}{}", &receiver[..max_len], method_call)
+                            } else {
+                                format!("{}{}", receiver, method_call)
+                            };
+                            Some(if is_struct_pat_shorthand_field {
+                                format!("{}: {}", receiver, sugg)
+                            } else {
+                                sugg
+                            })
                         }
                     }).peekable();
                 if suggestions.peek().is_some() {
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index d0e56acc8fb27..aaf628e6c260f 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -158,7 +158,6 @@ impl<R> BufReader<R> {
     /// # Examples
     ///
     /// ```no_run
-    /// # #![feature(bufreader_buffer)]
     /// use std::io::{BufReader, BufRead};
     /// use std::fs::File;
     ///
@@ -173,7 +172,7 @@ impl<R> BufReader<R> {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "bufreader_buffer", issue = "45323")]
+    #[stable(feature = "bufreader_buffer", since = "1.37.0")]
     pub fn buffer(&self) -> &[u8] {
         &self.buf[self.pos..self.cap]
     }
@@ -552,7 +551,6 @@ impl<W: Write> BufWriter<W> {
     /// # Examples
     ///
     /// ```no_run
-    /// # #![feature(bufreader_buffer)]
     /// use std::io::BufWriter;
     /// use std::net::TcpStream;
     ///
@@ -561,7 +559,7 @@ impl<W: Write> BufWriter<W> {
     /// // See how many bytes are currently buffered
     /// let bytes_buffered = buf_writer.buffer().len();
     /// ```
-    #[unstable(feature = "bufreader_buffer", issue = "45323")]
+    #[stable(feature = "bufreader_buffer", since = "1.37.0")]
     pub fn buffer(&self) -> &[u8] {
         &self.buf
     }
diff --git a/src/test/ui/async-await/issues/issue-61187.rs b/src/test/ui/async-await/issues/issue-61187.rs
new file mode 100644
index 0000000000000..8b939b43b8bd4
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-61187.rs
@@ -0,0 +1,9 @@
+// edition:2018
+#![feature(async_await)]
+
+fn main() {
+}
+
+async fn response(data: Vec<u8>) {
+    data.reverse(); //~ ERROR E0596
+}
diff --git a/src/test/ui/async-await/issues/issue-61187.stderr b/src/test/ui/async-await/issues/issue-61187.stderr
new file mode 100644
index 0000000000000..52fe15e8cf7c7
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-61187.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `async fn` parameter as mutable, as it is not declared as mutable
+  --> $DIR/issue-61187.rs:8:5
+   |
+LL | async fn response(data: Vec<u8>) {
+   |                   ---- help: consider changing this to be mutable: `mut data`
+LL |     data.reverse();
+   |     ^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/suggestions/issue-52820.rs b/src/test/ui/suggestions/issue-52820.rs
new file mode 100644
index 0000000000000..075b07f565203
--- /dev/null
+++ b/src/test/ui/suggestions/issue-52820.rs
@@ -0,0 +1,12 @@
+struct Bravery {
+    guts: String,
+    brains: String,
+}
+
+fn main() {
+    let guts = "mettle";
+    let _ = Bravery {
+        guts, //~ ERROR mismatched types
+        brains: guts.clone(), //~ ERROR mismatched types
+    };
+}
diff --git a/src/test/ui/suggestions/issue-52820.stderr b/src/test/ui/suggestions/issue-52820.stderr
new file mode 100644
index 0000000000000..fb568aca250e7
--- /dev/null
+++ b/src/test/ui/suggestions/issue-52820.stderr
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-52820.rs:9:9
+   |
+LL |         guts,
+   |         ^^^^
+   |         |
+   |         expected struct `std::string::String`, found &str
+   |         help: try using a conversion method: `guts: guts.to_string()`
+   |
+   = note: expected type `std::string::String`
+              found type `&str`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-52820.rs:10:17
+   |
+LL |         brains: guts.clone(),
+   |                 ^^^^^^^^^^^^
+   |                 |
+   |                 expected struct `std::string::String`, found &str
+   |                 help: try using a conversion method: `guts.to_string()`
+   |
+   = note: expected type `std::string::String`
+              found type `&str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.