about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-12-19 09:23:31 +0000
committerbors <bors@rust-lang.org>2022-12-19 09:23:31 +0000
commit4653c93e4442d88bf3278067183c8fdc0be74a1f (patch)
tree882fb217c4882e6a83e1cf8f385b72fef7328559
parent10723378900ba2d25fc5d8baf785e1082f385832 (diff)
parent2a57493fa1e3e59a298bec365a6afb3df7ea5e84 (diff)
downloadrust-4653c93e4442d88bf3278067183c8fdc0be74a1f.tar.gz
rust-4653c93e4442d88bf3278067183c8fdc0be74a1f.zip
Auto merge of #105892 - Dylan-DPC:rollup-eozolx4, r=Dylan-DPC
Rollup of 5 pull requests

Successful merges:

 - #105682 (Use `expose_addr()` in `fmt::Pointer`)
 - #105839 (Suggest a `T: Send` bound for `&mut T` upvars in `Send` generators)
 - #105864 (clippy::complexity fixes)
 - #105882 (Don't ICE in closure arg borrow suggestion)
 - #105889 (Fix `uninlined_format_args` in libtest)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs6
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/undo_log.rs8
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs7
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs4
-rw-r--r--compiler/rustc_parse/src/parser/path.rs3
-rw-r--r--compiler/rustc_passes/src/dead.rs1
-rw-r--r--compiler/rustc_session/src/filesearch.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs22
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs47
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/query_context.rs6
-rw-r--r--library/core/src/fmt/mod.rs4
-rw-r--r--library/test/src/cli.rs12
-rw-r--r--library/test/src/formatters/json.rs7
-rw-r--r--library/test/src/formatters/mod.rs2
-rw-r--r--library/test/src/formatters/pretty.rs2
-rw-r--r--library/test/src/lib.rs5
-rw-r--r--library/test/src/test_result.rs5
-rw-r--r--library/test/src/time.rs6
-rw-r--r--src/test/ui/generator/ref-upvar-not-send.rs31
-rw-r--r--src/test/ui/generator/ref-upvar-not-send.stderr50
-rw-r--r--src/test/ui/suggestions/enum-variant-arg-mismatch.rs10
-rw-r--r--src/test/ui/suggestions/enum-variant-arg-mismatch.stderr22
28 files changed, 181 insertions, 102 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index fe0d0747be6..0ef784a4453 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -600,7 +600,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.impl_trait_defs = current_impl_trait_defs;
         self.impl_trait_bounds = current_impl_trait_bounds;
 
-        debug_assert!(self.children.iter().find(|(id, _)| id == &def_id).is_none());
+        debug_assert!(!self.children.iter().any(|(id, _)| id == &def_id));
         self.children.push((def_id, hir::MaybeOwner::Owner(info)));
     }
 
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 5289de9b0ab..d8c22fbe59f 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -2059,12 +2059,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     ) -> Option<InitIndex> {
         let mpi = self.move_data.rev_lookup.find_local(local);
         let ii = &self.move_data.init_path_map[mpi];
-        for &index in ii {
-            if flow_state.ever_inits.contains(index) {
-                return Some(index);
-            }
-        }
-        None
+        ii.into_iter().find(|&&index| flow_state.ever_inits.contains(index)).copied()
     }
 
     /// Adds the place into the used mutable variables set
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 853a8b82853..5bf45a81e43 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -233,8 +233,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         // Set KCFI operand bundle
         let is_indirect_call = unsafe { llvm::LLVMIsAFunction(llfn).is_none() };
         let kcfi_bundle =
-            if self.tcx.sess.is_sanitizer_kcfi_enabled() && fn_abi.is_some() && is_indirect_call {
-                let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi.unwrap());
+            if self.tcx.sess.is_sanitizer_kcfi_enabled() && let Some(fn_abi) = fn_abi && is_indirect_call {
+                let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi);
                 Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
             } else {
                 None
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index 5266d8858d4..6eb120157da 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -123,7 +123,7 @@ fn try_filter_fat_archs<'a>(
 ) -> io::Result<Option<(&'a [u8], u64)>> {
     let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
 
-    let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() {
+    let desired = match archs.iter().find(|a| a.architecture() == target_arch) {
         Some(a) => a,
         None => return Ok(None),
     };
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index aef1c7ddcd0..c9d179de39f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1124,9 +1124,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         let hir = self.tcx.hir();
-        let cond_parent = hir.parent_iter(expr.hir_id).skip_while(|(_, node)| {
-            matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(op, _, _), .. }) if op.node == hir::BinOpKind::And)
-        }).next();
+        let cond_parent = hir.parent_iter(expr.hir_id).find(|(_, node)| {
+            !matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(op, _, _), .. }) if op.node == hir::BinOpKind::And)
+        });
         // Don't suggest:
         //     `let Some(_) = a.is_some() && b`
         //                     ++++++++++
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index ba990acfe6f..da2c6fbc05f 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -488,7 +488,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                         // If this empty region is from a universe that can
                         // name the placeholder, then the placeholder is
                         // larger; otherwise, the only ancestor is `'static`.
-                        if a_ui.can_name(placeholder.universe) { true } else { false }
+                        return a_ui.can_name(placeholder.universe);
                     }
                 }
             }
diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs
index 611961ab1cc..955c54e8515 100644
--- a/compiler/rustc_infer/src/infer/undo_log.rs
+++ b/compiler/rustc_infer/src/infer/undo_log.rs
@@ -87,18 +87,12 @@ impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
 
 /// The combined undo log for all the various unification tables. For each change to the storage
 /// for any kind of inference variable, we record an UndoLog entry in the vector here.
-#[derive(Clone)]
+#[derive(Clone, Default)]
 pub(crate) struct InferCtxtUndoLogs<'tcx> {
     logs: Vec<UndoLog<'tcx>>,
     num_open_snapshots: usize,
 }
 
-impl Default for InferCtxtUndoLogs<'_> {
-    fn default() -> Self {
-        Self { logs: Default::default(), num_open_snapshots: Default::default() }
-    }
-}
-
 /// The UndoLogs trait defines how we undo a particular kind of action (of type T). We can undo any
 /// action that is convertible into an UndoLog (per the From impls above).
 impl<'tcx, T> UndoLogs<T> for InferCtxtUndoLogs<'tcx>
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index fc08d58cc40..0e18ba73d71 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -103,12 +103,7 @@ impl EffectiveVisibilities {
 
     pub fn public_at_level(&self, id: LocalDefId) -> Option<Level> {
         self.effective_vis(id).and_then(|effective_vis| {
-            for level in Level::all_levels() {
-                if effective_vis.is_public_at_level(level) {
-                    return Some(level);
-                }
-            }
-            None
+            Level::all_levels().into_iter().find(|&level| effective_vis.is_public_at_level(level))
         })
     }
 
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 558a372fb1e..3a2bf051516 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -182,7 +182,7 @@ fn replace_flattened_locals<'tcx>(
     let mut fragments = IndexVec::new();
     for (k, v) in &replacements.fields {
         fragments.ensure_contains_elem(k.local, || Vec::new());
-        fragments[k.local].push((&k.projection[..], *v));
+        fragments[k.local].push((k.projection, *v));
     }
     debug!(?fragments);
 
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 10ea4d29cfe..deeeb9af4eb 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -595,8 +595,8 @@ fn check_recursion_limit<'tcx>(
         let def_path_str = tcx.def_path_str(def_id);
         let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance);
         let mut path = PathBuf::new();
-        let was_written = if written_to_path.is_some() {
-            path = written_to_path.unwrap();
+        let was_written = if let Some(written_to_path) = written_to_path {
+            path = written_to_path;
             Some(())
         } else {
             None
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 2d432e3f5bd..5333d3b8587 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -277,8 +277,7 @@ impl<'a> Parser<'a> {
                         if let Some(arg) = args
                             .iter()
                             .rev()
-                            .skip_while(|arg| matches!(arg, AngleBracketedArg::Constraint(_)))
-                            .next()
+                            .find(|arg| !matches!(arg, AngleBracketedArg::Constraint(_)))
                         {
                             err.span_suggestion_verbose(
                                 arg.span().shrink_to_hi(),
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index a71ae717a50..f5556738bff 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -787,7 +787,6 @@ impl<'tcx> DeadVisitor<'tcx> {
         let mut dead_codes = dead_codes
             .iter()
             .filter(|v| !v.name.as_str().starts_with('_'))
-            .map(|v| v)
             .collect::<Vec<&DeadVariant>>();
         if dead_codes.is_empty() {
             return;
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 1855a49c1ec..6f1b31ff9c3 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -122,7 +122,7 @@ pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
     let target = crate::config::host_triple();
     let mut sysroot_candidates: SmallVec<[PathBuf; 2]> =
         smallvec![get_or_default_sysroot().expect("Failed finding sysroot")];
-    let path = current_dll_path().and_then(|s| Ok(s.canonicalize().map_err(|e| e.to_string())?));
+    let path = current_dll_path().and_then(|s| s.canonicalize().map_err(|e| e.to_string()));
     if let Ok(dll) = path {
         // use `parent` twice to chop off the file name and then also the
         // directory containing the dll which should be either `lib` or `bin`.
@@ -165,7 +165,7 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
     }
 
     fn default_from_rustc_driver_dll() -> Result<PathBuf, String> {
-        let dll = current_dll_path().and_then(|s| Ok(canonicalize(s)))?;
+        let dll = current_dll_path().map(|s| canonicalize(s))?;
 
         // `dll` will be in one of the following two:
         // - compiler's libdir: $sysroot/lib/*.dll
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index c9ddb084d63..0845b1b6b09 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -99,13 +99,8 @@ fn is_c_void_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
         ty::Adt(adt_def, ..) => {
             let def_id = adt_def.0.did;
             let crate_name = tcx.crate_name(def_id.krate);
-            if tcx.item_name(def_id).as_str() == "c_void"
+            tcx.item_name(def_id).as_str() == "c_void"
                 && (crate_name == sym::core || crate_name == sym::std || crate_name == sym::libc)
-            {
-                true
-            } else {
-                false
-            }
         }
         _ => false,
     }
@@ -267,8 +262,7 @@ fn encode_predicates<'tcx>(
 ) -> String {
     // <predicate1[..predicateN]>E as part of vendor extended type
     let mut s = String::new();
-    let predicates: Vec<ty::PolyExistentialPredicate<'tcx>> =
-        predicates.iter().map(|predicate| predicate).collect();
+    let predicates: Vec<ty::PolyExistentialPredicate<'tcx>> = predicates.iter().collect();
     for predicate in predicates {
         s.push_str(&encode_predicate(tcx, predicate, dict, options));
     }
@@ -322,7 +316,7 @@ fn encode_substs<'tcx>(
 ) -> String {
     // [I<subst1..substN>E] as part of vendor extended type
     let mut s = String::new();
-    let substs: Vec<GenericArg<'_>> = substs.iter().map(|subst| subst).collect();
+    let substs: Vec<GenericArg<'_>> = substs.iter().collect();
     if !substs.is_empty() {
         s.push('I');
         for subst in substs {
@@ -703,11 +697,8 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
                         tcx.layout_of(param_env.and(ty)).map_or(false, |layout| layout.is_zst());
                     !is_zst
                 });
-                if field.is_none() {
-                    // Transform repr(transparent) types without non-ZST field into ()
-                    ty = tcx.mk_unit();
-                } else {
-                    let ty0 = tcx.type_of(field.unwrap().did);
+                if let Some(field) = field {
+                    let ty0 = tcx.type_of(field.did);
                     // Generalize any repr(transparent) user-defined type that is either a pointer
                     // or reference, and either references itself or any other type that contains or
                     // references itself, to avoid a reference cycle.
@@ -720,6 +711,9 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
                     } else {
                         ty = transform_ty(tcx, ty0, options);
                     }
+                } else {
+                    // Transform repr(transparent) types without non-ZST field into ()
+                    ty = tcx.mk_unit();
                 }
             } else {
                 ty = tcx.mk_adt(*adt_def, transform_substs(tcx, substs, options));
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 5a4c87c56d5..036e8f6d47b 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1789,7 +1789,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         self.note_conflicting_closure_bounds(cause, &mut err);
 
         if let Some(found_node) = found_node {
-            hint_missing_borrow(span, found_span, found, expected, found_node, &mut err);
+            hint_missing_borrow(span, found, expected, found_node, &mut err);
         }
 
         err
@@ -2344,28 +2344,33 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
             }
             GeneratorInteriorOrUpvar::Upvar(upvar_span) => {
-                // `Some(ref_ty)` if `target_ty` is `&T` and `T` fails to impl `Sync`
-                let refers_to_non_sync = match target_ty.kind() {
-                    ty::Ref(_, ref_ty, _) => match self.evaluate_obligation(&obligation) {
-                        Ok(eval) if !eval.may_apply() => Some(ref_ty),
+                // `Some((ref_ty, is_mut))` if `target_ty` is `&T` or `&mut T` and fails to impl `Send`
+                let non_send = match target_ty.kind() {
+                    ty::Ref(_, ref_ty, mutability) => match self.evaluate_obligation(&obligation) {
+                        Ok(eval) if !eval.may_apply() => Some((ref_ty, mutability.is_mut())),
                         _ => None,
                     },
                     _ => None,
                 };
 
-                let (span_label, span_note) = match refers_to_non_sync {
-                    // if `target_ty` is `&T` and `T` fails to impl `Sync`,
-                    // include suggestions to make `T: Sync` so that `&T: Send`
-                    Some(ref_ty) => (
-                        format!(
-                            "has type `{}` which {}, because `{}` is not `Sync`",
-                            target_ty, trait_explanation, ref_ty
-                        ),
-                        format!(
-                            "captured value {} because `&` references cannot be sent unless their referent is `Sync`",
-                            trait_explanation
-                        ),
-                    ),
+                let (span_label, span_note) = match non_send {
+                    // if `target_ty` is `&T` or `&mut T` and fails to impl `Send`,
+                    // include suggestions to make `T: Sync` so that `&T: Send`,
+                    // or to make `T: Send` so that `&mut T: Send`
+                    Some((ref_ty, is_mut)) => {
+                        let ref_ty_trait = if is_mut { "Send" } else { "Sync" };
+                        let ref_kind = if is_mut { "&mut" } else { "&" };
+                        (
+                            format!(
+                                "has type `{}` which {}, because `{}` is not `{}`",
+                                target_ty, trait_explanation, ref_ty, ref_ty_trait
+                            ),
+                            format!(
+                                "captured value {} because `{}` references cannot be sent unless their referent is `{}`",
+                                trait_explanation, ref_kind, ref_ty_trait
+                            ),
+                        )
+                    }
                     None => (
                         format!("has type `{}` which {}", target_ty, trait_explanation),
                         format!("captured value {}", trait_explanation),
@@ -3455,7 +3460,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 /// Add a hint to add a missing borrow or remove an unnecessary one.
 fn hint_missing_borrow<'tcx>(
     span: Span,
-    found_span: Span,
     found: Ty<'tcx>,
     expected: Ty<'tcx>,
     found_node: Node<'_>,
@@ -3474,9 +3478,8 @@ fn hint_missing_borrow<'tcx>(
         }
     };
 
-    let fn_decl = found_node
-        .fn_decl()
-        .unwrap_or_else(|| span_bug!(found_span, "found node must be a function"));
+    // This could be a variant constructor, for example.
+    let Some(fn_decl) = found_node.fn_decl() else { return; };
 
     let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
 
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
index adab343ac98..e4f3e7928da 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
@@ -76,11 +76,7 @@ mod rustc {
                 }
             };
 
-            let ret = if self.visibility(def_id).is_accessible_from(parent, *self) {
-                true
-            } else {
-                false
-            };
+            let ret: bool = self.visibility(def_id).is_accessible_from(parent, *self);
 
             trace!(?ret, "ret");
             ret
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 122da675f7e..5f4a666de92 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -2471,8 +2471,8 @@ impl Display for char {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Pointer for *const T {
     fn fmt(&self, f: &mut Formatter<'_>) -> Result {
-        // Cast is needed here because `.addr()` requires `T: Sized`.
-        pointer_fmt_inner((*self as *const ()).addr(), f)
+        // Cast is needed here because `.expose_addr()` requires `T: Sized`.
+        pointer_fmt_inner((*self as *const ()).expose_addr(), f)
     }
 }
 
diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs
index 524658bce13..796796e07a9 100644
--- a/library/test/src/cli.rs
+++ b/library/test/src/cli.rs
@@ -354,8 +354,7 @@ fn get_shuffle_seed(matches: &getopts::Matches, allow_unstable: bool) -> OptPart
             Err(e) => {
                 return Err(format!(
                     "argument for --shuffle-seed must be a number \
-                     (error: {})",
-                    e
+                     (error: {e})"
                 ));
             }
         },
@@ -383,8 +382,7 @@ fn get_test_threads(matches: &getopts::Matches) -> OptPartRes<Option<usize>> {
             Err(e) => {
                 return Err(format!(
                     "argument for --test-threads must be a number > 0 \
-                     (error: {})",
-                    e
+                     (error: {e})"
                 ));
             }
         },
@@ -418,8 +416,7 @@ fn get_format(
         Some(v) => {
             return Err(format!(
                 "argument for --format must be pretty, terse, json or junit (was \
-                 {})",
-                v
+                 {v})"
             ));
         }
     };
@@ -436,8 +433,7 @@ fn get_color_config(matches: &getopts::Matches) -> OptPartRes<ColorConfig> {
         Some(v) => {
             return Err(format!(
                 "argument for --color must be auto, always, or never (was \
-                 {})",
-                v
+                 {v})"
             ));
         }
     };
diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs
index c07fdafb167..5526aadb67f 100644
--- a/library/test/src/formatters/json.rs
+++ b/library/test/src/formatters/json.rs
@@ -53,7 +53,7 @@ impl<T: Write> JsonFormatter<T> {
             self.write_message(&*format!(r#", "stdout": "{}""#, EscapedString(stdout)))?;
         }
         if let Some(extra) = extra {
-            self.write_message(&*format!(r#", {}"#, extra))?;
+            self.write_message(&*format!(r#", {extra}"#))?;
         }
         self.writeln_message(" }")
     }
@@ -62,13 +62,12 @@ impl<T: Write> JsonFormatter<T> {
 impl<T: Write> OutputFormatter for JsonFormatter<T> {
     fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option<u64>) -> io::Result<()> {
         let shuffle_seed_json = if let Some(shuffle_seed) = shuffle_seed {
-            format!(r#", "shuffle_seed": {}"#, shuffle_seed)
+            format!(r#", "shuffle_seed": {shuffle_seed}"#)
         } else {
             String::new()
         };
         self.writeln_message(&*format!(
-            r#"{{ "type": "suite", "event": "started", "test_count": {}{} }}"#,
-            test_count, shuffle_seed_json
+            r#"{{ "type": "suite", "event": "started", "test_count": {test_count}{shuffle_seed_json} }}"#
         ))
     }
 
diff --git a/library/test/src/formatters/mod.rs b/library/test/src/formatters/mod.rs
index cb80859759f..cb67b6491a3 100644
--- a/library/test/src/formatters/mod.rs
+++ b/library/test/src/formatters/mod.rs
@@ -38,5 +38,5 @@ pub(crate) fn write_stderr_delimiter(test_output: &mut Vec<u8>, test_name: &Test
         Some(_) => test_output.push(b'\n'),
         None => (),
     }
-    writeln!(test_output, "---- {} stderr ----", test_name).unwrap();
+    writeln!(test_output, "---- {test_name} stderr ----").unwrap();
 }
diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs
index 69420222980..0299c8b5433 100644
--- a/library/test/src/formatters/pretty.rs
+++ b/library/test/src/formatters/pretty.rs
@@ -47,7 +47,7 @@ impl<T: Write> PrettyFormatter<T> {
 
     pub fn write_ignored(&mut self, message: Option<&'static str>) -> io::Result<()> {
         if let Some(message) = message {
-            self.write_short_result(&format!("ignored, {}", message), term::color::YELLOW)
+            self.write_short_result(&format!("ignored, {message}"), term::color::YELLOW)
         } else {
             self.write_short_result("ignored", term::color::YELLOW)
         }
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 256c9e8d141..f6a41bbb88c 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -213,8 +213,7 @@ pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> {
     } else {
         Err(format!(
             "the test returned a termination value with a non-zero status code \
-             ({}) which indicates a failure",
-            code
+             ({code}) which indicates a failure"
         ))
     }
 }
@@ -750,7 +749,7 @@ fn spawn_test_subprocess(
         })() {
             Ok(r) => r,
             Err(e) => {
-                write!(&mut test_output, "Unexpected error: {}", e).unwrap();
+                write!(&mut test_output, "Unexpected error: {e}").unwrap();
                 TrFailed
             }
         };
diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs
index 7f44d6e3d0f..7c5b0d6c0f7 100644
--- a/library/test/src/test_result.rs
+++ b/library/test/src/test_result.rs
@@ -44,9 +44,8 @@ pub fn calc_result<'a>(
             } else if let Some(panic_str) = maybe_panic_str {
                 TestResult::TrFailedMsg(format!(
                     r#"panic did not contain expected string
-      panic message: `{:?}`,
- expected substring: `{:?}`"#,
-                    panic_str, msg
+      panic message: `{panic_str:?}`,
+ expected substring: `{msg:?}`"#
                 ))
             } else {
                 TestResult::TrFailedMsg(format!(
diff --git a/library/test/src/time.rs b/library/test/src/time.rs
index 8c64e5d1b73..7fd69d7f7e7 100644
--- a/library/test/src/time.rs
+++ b/library/test/src/time.rs
@@ -107,16 +107,14 @@ impl TimeThreshold {
         let durations_str = env::var(env_var_name).ok()?;
         let (warn_str, critical_str) = durations_str.split_once(',').unwrap_or_else(|| {
             panic!(
-                "Duration variable {} expected to have 2 numbers separated by comma, but got {}",
-                env_var_name, durations_str
+                "Duration variable {env_var_name} expected to have 2 numbers separated by comma, but got {durations_str}"
             )
         });
 
         let parse_u64 = |v| {
             u64::from_str(v).unwrap_or_else(|_| {
                 panic!(
-                    "Duration value in variable {} is expected to be a number, but got {}",
-                    env_var_name, v
+                    "Duration value in variable {env_var_name} is expected to be a number, but got {v}"
                 )
             })
         };
diff --git a/src/test/ui/generator/ref-upvar-not-send.rs b/src/test/ui/generator/ref-upvar-not-send.rs
new file mode 100644
index 00000000000..eb9ef63ecfc
--- /dev/null
+++ b/src/test/ui/generator/ref-upvar-not-send.rs
@@ -0,0 +1,31 @@
+// For `Send` generators, suggest a `T: Sync` requirement for `&T` upvars,
+// and suggest a `T: Send` requirement for `&mut T` upvars.
+
+#![feature(generators)]
+
+fn assert_send<T: Send>(_: T) {}
+//~^ NOTE required by a bound in `assert_send`
+//~| NOTE required by this bound in `assert_send`
+//~| NOTE required by a bound in `assert_send`
+//~| NOTE required by this bound in `assert_send`
+
+fn main() {
+    let x: &*mut () = &std::ptr::null_mut();
+    let y: &mut *mut () = &mut std::ptr::null_mut();
+    assert_send(move || {
+        //~^ ERROR generator cannot be sent between threads safely
+        //~| NOTE generator is not `Send`
+        yield;
+        let _x = x;
+    });
+    //~^^ NOTE captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
+    //~| NOTE has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync`
+    assert_send(move || {
+        //~^ ERROR generator cannot be sent between threads safely
+        //~| NOTE generator is not `Send`
+        yield;
+        let _y = y;
+    });
+    //~^^ NOTE captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send`
+    //~| NOTE has type `&mut *mut ()` which is not `Send`, because `*mut ()` is not `Send`
+}
diff --git a/src/test/ui/generator/ref-upvar-not-send.stderr b/src/test/ui/generator/ref-upvar-not-send.stderr
new file mode 100644
index 00000000000..689ace67e34
--- /dev/null
+++ b/src/test/ui/generator/ref-upvar-not-send.stderr
@@ -0,0 +1,50 @@
+error: generator cannot be sent between threads safely
+  --> $DIR/ref-upvar-not-send.rs:15:17
+   |
+LL |       assert_send(move || {
+   |  _________________^
+LL | |
+LL | |
+LL | |         yield;
+LL | |         let _x = x;
+LL | |     });
+   | |_____^ generator is not `Send`
+   |
+   = help: the trait `Sync` is not implemented for `*mut ()`
+note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
+  --> $DIR/ref-upvar-not-send.rs:19:18
+   |
+LL |         let _x = x;
+   |                  ^ has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync`
+note: required by a bound in `assert_send`
+  --> $DIR/ref-upvar-not-send.rs:6:19
+   |
+LL | fn assert_send<T: Send>(_: T) {}
+   |                   ^^^^ required by this bound in `assert_send`
+
+error: generator cannot be sent between threads safely
+  --> $DIR/ref-upvar-not-send.rs:23:17
+   |
+LL |       assert_send(move || {
+   |  _________________^
+LL | |
+LL | |
+LL | |         yield;
+LL | |         let _y = y;
+LL | |     });
+   | |_____^ generator is not `Send`
+   |
+   = help: within `[generator@$DIR/ref-upvar-not-send.rs:23:17: 23:24]`, the trait `Send` is not implemented for `*mut ()`
+note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send`
+  --> $DIR/ref-upvar-not-send.rs:27:18
+   |
+LL |         let _y = y;
+   |                  ^ has type `&mut *mut ()` which is not `Send`, because `*mut ()` is not `Send`
+note: required by a bound in `assert_send`
+  --> $DIR/ref-upvar-not-send.rs:6:19
+   |
+LL | fn assert_send<T: Send>(_: T) {}
+   |                   ^^^^ required by this bound in `assert_send`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/suggestions/enum-variant-arg-mismatch.rs b/src/test/ui/suggestions/enum-variant-arg-mismatch.rs
new file mode 100644
index 00000000000..8de5bae92fc
--- /dev/null
+++ b/src/test/ui/suggestions/enum-variant-arg-mismatch.rs
@@ -0,0 +1,10 @@
+pub enum Sexpr<'a> {
+    Ident(&'a str),
+}
+
+fn map<'a, F: Fn(String) -> Sexpr<'a>>(f: F) {}
+
+fn main() {
+    map(Sexpr::Ident);
+    //~^ ERROR type mismatch in function arguments
+}
diff --git a/src/test/ui/suggestions/enum-variant-arg-mismatch.stderr b/src/test/ui/suggestions/enum-variant-arg-mismatch.stderr
new file mode 100644
index 00000000000..f76019b7000
--- /dev/null
+++ b/src/test/ui/suggestions/enum-variant-arg-mismatch.stderr
@@ -0,0 +1,22 @@
+error[E0631]: type mismatch in function arguments
+  --> $DIR/enum-variant-arg-mismatch.rs:8:9
+   |
+LL |     Ident(&'a str),
+   |     ----- found signature defined here
+...
+LL |     map(Sexpr::Ident);
+   |     --- ^^^^^^^^^^^^ expected due to this
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = note: expected function signature `fn(String) -> _`
+              found function signature `fn(&str) -> _`
+note: required by a bound in `map`
+  --> $DIR/enum-variant-arg-mismatch.rs:5:15
+   |
+LL | fn map<'a, F: Fn(String) -> Sexpr<'a>>(f: F) {}
+   |               ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0631`.