about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs98
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs12
-rw-r--r--compiler/rustc_infer/messages.ftl3
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs11
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs75
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs2
-rw-r--r--compiler/rustc_lint/src/unused.rs24
-rw-r--r--library/core/src/clone.rs5
-rw-r--r--library/core/src/cmp.rs10
-rw-r--r--library/core/src/convert/num.rs7
-rw-r--r--library/core/src/ffi/c_str.rs4
-rw-r--r--library/core/src/fmt/nofloat.rs2
-rw-r--r--library/core/src/lib.rs8
-rw-r--r--library/core/src/marker.rs8
-rw-r--r--library/core/src/num/f128.rs16
-rw-r--r--library/core/src/num/f16.rs16
-rw-r--r--library/core/src/ops/arith.rs22
-rw-r--r--library/core/src/primitive_docs.rs30
-rw-r--r--library/std/src/f128.rs11
-rw-r--r--library/std/src/f128/tests.rs40
-rw-r--r--library/std/src/f16.rs11
-rw-r--r--library/std/src/f16/tests.rs46
-rw-r--r--library/std/src/fs.rs14
-rw-r--r--library/std/src/lib.rs17
-rw-r--r--tests/codegen/float/f128.rs129
-rw-r--r--tests/codegen/float/f16.rs129
-rw-r--r--tests/ui/array-slice-vec/vector-no-ann.stderr2
-rw-r--r--tests/ui/async-await/track-caller/async-closure-gate.afn.stderr4
-rw-r--r--tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr4
-rw-r--r--tests/ui/const-generics/defaults/doesnt_infer.rs2
-rw-r--r--tests/ui/const-generics/defaults/doesnt_infer.stderr2
-rw-r--r--tests/ui/const-generics/generic_arg_infer/issue-91614.stderr2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr2
-rw-r--r--tests/ui/generic-const-items/inference-failure.stderr2
-rw-r--r--tests/ui/generic-const-items/parameter-defaults.stderr2
-rw-r--r--tests/ui/imports/redundant-import-extern-prelude.rs17
-rw-r--r--tests/ui/imports/redundant-import-extern-prelude.stderr (renamed from tests/ui/imports/redundant-import-issue-121915.stderr)6
-rw-r--r--tests/ui/imports/redundant-import-issue-121915.rs9
-rw-r--r--tests/ui/imports/redundant-import-lang-prelude-attr.rs18
-rw-r--r--tests/ui/imports/redundant-import-lang-prelude-attr.stderr14
-rw-r--r--tests/ui/imports/redundant-import-lang-prelude.rs18
-rw-r--r--tests/ui/imports/redundant-import-lang-prelude.stderr14
-rw-r--r--tests/ui/imports/redundant-import-undetected-macro-use-prelude.rs23
-rw-r--r--tests/ui/inference/cannot-infer-closure-circular.rs2
-rw-r--r--tests/ui/inference/cannot-infer-closure-circular.stderr2
-rw-r--r--tests/ui/inference/erase-type-params-in-label.stderr4
-rw-r--r--tests/ui/inference/issue-104649.stderr2
-rw-r--r--tests/ui/inference/issue-72690.stderr2
-rw-r--r--tests/ui/inference/issue-83606.rs2
-rw-r--r--tests/ui/inference/issue-83606.stderr2
-rw-r--r--tests/ui/issues/issue-11771.stderr12
-rw-r--r--tests/ui/issues/issue-12187-1.stderr2
-rw-r--r--tests/ui/issues/issue-12187-2.stderr2
-rw-r--r--tests/ui/issues/issue-17551.stderr2
-rw-r--r--tests/ui/issues/issue-23046.stderr2
-rw-r--r--tests/ui/issues/issue-50582.stderr6
-rw-r--r--tests/ui/issues/issue-98299.stderr2
-rw-r--r--tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.rs39
-rw-r--r--tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.stderr40
-rw-r--r--tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr2
-rw-r--r--tests/ui/mismatched_types/binops.stderr18
-rw-r--r--tests/ui/suggestions/return-closures.stderr2
-rw-r--r--tests/ui/traits/copy-guessing.rs2
-rw-r--r--tests/ui/traits/copy-guessing.stderr2
-rw-r--r--tests/ui/traits/issue-77982.stderr4
-rw-r--r--tests/ui/type-inference/or_else-multiple-type-params.stderr2
-rw-r--r--tests/ui/typeck/return_type_containing_closure.rs2
-rw-r--r--tests/ui/typeck/return_type_containing_closure.stderr6
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr2
70 files changed, 872 insertions, 186 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index a705d3bc107..c1bf65367aa 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -30,7 +30,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
 use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::FieldIdx;
 use rustc_target::spec::abi;
 use rustc_trait_selection::infer::InferCtxtExt;
@@ -1383,7 +1383,9 @@ fn infer_return_ty_for_fn_sig<'tcx>(
                     Applicability::MachineApplicable,
                 );
                 should_recover = true;
-            } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, def_id) {
+            } else if let Some(sugg) =
+                suggest_impl_trait(&tcx.infer_ctxt().build(), tcx.param_env(def_id), ret_ty)
+            {
                 diag.span_suggestion(
                     ty.span,
                     "replace with an appropriate return type",
@@ -1426,11 +1428,10 @@ fn infer_return_ty_for_fn_sig<'tcx>(
     }
 }
 
-fn suggest_impl_trait<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub fn suggest_impl_trait<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
     ret_ty: Ty<'tcx>,
-    span: Span,
-    def_id: LocalDefId,
 ) -> Option<String> {
     let format_as_assoc: fn(_, _, _, _, _) -> _ =
         |tcx: TyCtxt<'tcx>,
@@ -1464,24 +1465,28 @@ fn suggest_impl_trait<'tcx>(
 
     for (trait_def_id, assoc_item_def_id, formatter) in [
         (
-            tcx.get_diagnostic_item(sym::Iterator),
-            tcx.get_diagnostic_item(sym::IteratorItem),
+            infcx.tcx.get_diagnostic_item(sym::Iterator),
+            infcx.tcx.get_diagnostic_item(sym::IteratorItem),
             format_as_assoc,
         ),
         (
-            tcx.lang_items().future_trait(),
-            tcx.get_diagnostic_item(sym::FutureOutput),
+            infcx.tcx.lang_items().future_trait(),
+            infcx.tcx.get_diagnostic_item(sym::FutureOutput),
             format_as_assoc,
         ),
-        (tcx.lang_items().fn_trait(), tcx.lang_items().fn_once_output(), format_as_parenthesized),
         (
-            tcx.lang_items().fn_mut_trait(),
-            tcx.lang_items().fn_once_output(),
+            infcx.tcx.lang_items().fn_trait(),
+            infcx.tcx.lang_items().fn_once_output(),
+            format_as_parenthesized,
+        ),
+        (
+            infcx.tcx.lang_items().fn_mut_trait(),
+            infcx.tcx.lang_items().fn_once_output(),
             format_as_parenthesized,
         ),
         (
-            tcx.lang_items().fn_once_trait(),
-            tcx.lang_items().fn_once_output(),
+            infcx.tcx.lang_items().fn_once_trait(),
+            infcx.tcx.lang_items().fn_once_output(),
             format_as_parenthesized,
         ),
     ] {
@@ -1491,36 +1496,45 @@ fn suggest_impl_trait<'tcx>(
         let Some(assoc_item_def_id) = assoc_item_def_id else {
             continue;
         };
-        if tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
+        if infcx.tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
             continue;
         }
-        let param_env = tcx.param_env(def_id);
-        let infcx = tcx.infer_ctxt().build();
-        let args = ty::GenericArgs::for_item(tcx, trait_def_id, |param, _| {
-            if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(span, param) }
+        let sugg = infcx.probe(|_| {
+            let args = ty::GenericArgs::for_item(infcx.tcx, trait_def_id, |param, _| {
+                if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(DUMMY_SP, param) }
+            });
+            if !infcx
+                .type_implements_trait(trait_def_id, args, param_env)
+                .must_apply_modulo_regions()
+            {
+                return None;
+            }
+            let ocx = ObligationCtxt::new(&infcx);
+            let item_ty = ocx.normalize(
+                &ObligationCause::dummy(),
+                param_env,
+                Ty::new_projection(infcx.tcx, assoc_item_def_id, args),
+            );
+            // FIXME(compiler-errors): We may benefit from resolving regions here.
+            if ocx.select_where_possible().is_empty()
+                && let item_ty = infcx.resolve_vars_if_possible(item_ty)
+                && let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
+                && let Some(sugg) = formatter(
+                    infcx.tcx,
+                    infcx.resolve_vars_if_possible(args),
+                    trait_def_id,
+                    assoc_item_def_id,
+                    item_ty,
+                )
+            {
+                return Some(sugg);
+            }
+
+            None
         });
-        if !infcx.type_implements_trait(trait_def_id, args, param_env).must_apply_modulo_regions() {
-            continue;
-        }
-        let ocx = ObligationCtxt::new(&infcx);
-        let item_ty = ocx.normalize(
-            &ObligationCause::misc(span, def_id),
-            param_env,
-            Ty::new_projection(tcx, assoc_item_def_id, args),
-        );
-        // FIXME(compiler-errors): We may benefit from resolving regions here.
-        if ocx.select_where_possible().is_empty()
-            && let item_ty = infcx.resolve_vars_if_possible(item_ty)
-            && let Some(item_ty) = item_ty.make_suggestable(tcx, false, None)
-            && let Some(sugg) = formatter(
-                tcx,
-                infcx.resolve_vars_if_possible(args),
-                trait_def_id,
-                assoc_item_def_id,
-                item_ty,
-            )
-        {
-            return Some(sugg);
+
+        if sugg.is_some() {
+            return sugg;
         }
     }
     None
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 442bfd75746..1e1136ef467 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -20,6 +20,7 @@ use rustc_hir::{
     CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node,
     Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
 };
+use rustc_hir_analysis::collect::suggest_impl_trait;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
 use rustc_infer::traits::{self};
 use rustc_middle::lint::in_external_macro;
@@ -814,17 +815,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() },
                     );
                     return true;
-                } else if let ty::Closure(_, args) = found.kind()
-                    // FIXME(compiler-errors): Get better at printing binders...
-                    && let closure = args.as_closure()
-                    && closure.sig().is_suggestable(self.tcx, false)
-                {
+                } else if let Some(sugg) = suggest_impl_trait(self, self.param_env, found) {
                     err.subdiagnostic(
                         self.dcx(),
-                        errors::AddReturnTypeSuggestion::Add {
-                            span,
-                            found: closure.print_as_impl_trait().to_string(),
-                        },
+                        errors::AddReturnTypeSuggestion::Add { span, found: sugg },
                     );
                     return true;
                 } else {
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index fdb6ab8f59b..64f52ea7ac1 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -144,6 +144,9 @@ infer_fps_items_are_distinct = fn items are distinct from fn pointers
 infer_fps_remove_ref = consider removing the reference
 infer_fps_use_ref = consider using a reference
 infer_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
+
+infer_full_type_written = the full type name has been written to '{$path}'
+
 infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
 infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
 infer_label_bad = {$bad_kind ->
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 6192eaf3c3a..4593108edac 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -18,6 +18,8 @@ use crate::infer::error_reporting::{
     ObligationCauseAsDiagArg,
 };
 
+use std::path::PathBuf;
+
 pub mod note_and_explain;
 
 #[derive(Diagnostic)]
@@ -47,6 +49,9 @@ pub struct AnnotationRequired<'a> {
     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
+    #[note(infer_full_type_written)]
+    pub was_written: Option<()>,
+    pub path: PathBuf,
 }
 
 // Copy of `AnnotationRequired` for E0283
@@ -65,6 +70,9 @@ pub struct AmbiguousImpl<'a> {
     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
+    #[note(infer_full_type_written)]
+    pub was_written: Option<()>,
+    pub path: PathBuf,
 }
 
 // Copy of `AnnotationRequired` for E0284
@@ -83,6 +91,9 @@ pub struct AmbiguousReturn<'a> {
     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
+    #[note(infer_full_type_written)]
+    pub was_written: Option<()>,
+    pub path: PathBuf,
 }
 
 // Used when a better one isn't available
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index f89ed256a08..3b5658ed0ee 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -18,13 +18,15 @@ use rustc_middle::infer::unify_key::{
 };
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
-use rustc_middle::ty::{self, InferConst};
-use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
-use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
+use rustc_middle::ty::{
+    self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Ty, TyCtxt,
+    TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
+};
 use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::{BytePos, Span};
+use rustc_span::{BytePos, Span, DUMMY_SP};
 use std::borrow::Cow;
 use std::iter;
+use std::path::PathBuf;
 
 pub enum TypeAnnotationNeeded {
     /// ```compile_fail,E0282
@@ -153,6 +155,29 @@ impl UnderspecifiedArgKind {
     }
 }
 
+struct ClosureEraser<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'tcx> {
+    fn interner(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        match ty.kind() {
+            ty::Closure(_, args) => {
+                let closure_sig = args.as_closure().sig();
+                Ty::new_fn_ptr(
+                    self.tcx,
+                    self.tcx.signature_unclosure(closure_sig, hir::Unsafety::Normal),
+                )
+            }
+            _ => ty.super_fold_with(self),
+        }
+    }
+}
+
 fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> {
     let mut printer = FmtPrinter::new(infcx.tcx, ns);
     let ty_getter = move |ty_vid| {
@@ -209,6 +234,10 @@ fn ty_to_string<'tcx>(
 ) -> String {
     let mut printer = fmt_printer(infcx, Namespace::TypeNS);
     let ty = infcx.resolve_vars_if_possible(ty);
+    // We use `fn` ptr syntax for closures, but this only works when the closure
+    // does not capture anything.
+    let ty = ty.fold_with(&mut ClosureEraser { tcx: infcx.tcx });
+
     match (ty.kind(), called_method_def_id) {
         // We don't want the regular output for `fn`s because it includes its path in
         // invalid pseudo-syntax, we want the `fn`-pointer output instead.
@@ -223,11 +252,6 @@ fn ty_to_string<'tcx>(
             "Vec<_>".to_string()
         }
         _ if ty.is_ty_or_numeric_infer() => "/* Type */".to_string(),
-        // FIXME: The same thing for closures, but this only works when the closure
-        // does not capture anything.
-        //
-        // We do have to hide the `extern "rust-call"` ABI in that case though,
-        // which is too much of a bother for now.
         _ => {
             ty.print(&mut printer).unwrap();
             printer.into_buffer()
@@ -387,6 +411,8 @@ impl<'tcx> InferCtxt<'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
+                was_written: None,
+                path: Default::default(),
             }),
             TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
                 span,
@@ -396,6 +422,8 @@ impl<'tcx> InferCtxt<'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
+                was_written: None,
+                path: Default::default(),
             }),
             TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
                 span,
@@ -405,6 +433,8 @@ impl<'tcx> InferCtxt<'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
+                was_written: None,
+                path: Default::default(),
             }),
         }
     }
@@ -442,7 +472,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             return self.bad_inference_failure_err(failure_span, arg_data, error_code);
         };
 
-        let (source_kind, name) = kind.ty_localized_msg(self);
+        let (source_kind, name, path) = kind.ty_localized_msg(self);
         let failure_span = if should_label_span && !failure_span.overlaps(span) {
             Some(failure_span)
         } else {
@@ -518,7 +548,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
                                 GenericArgKind::Type(_) => self
                                     .next_ty_var(TypeVariableOrigin {
-                                        span: rustc_span::DUMMY_SP,
+                                        span: DUMMY_SP,
                                         kind: TypeVariableOriginKind::MiscVariable,
                                     })
                                     .into(),
@@ -526,7 +556,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                     .next_const_var(
                                         arg.ty(),
                                         ConstVariableOrigin {
-                                            span: rustc_span::DUMMY_SP,
+                                            span: DUMMY_SP,
                                             kind: ConstVariableOriginKind::MiscVariable,
                                         },
                                     )
@@ -547,7 +577,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             }
             InferSourceKind::FullyQualifiedMethodCall { receiver, successor, args, def_id } => {
                 let placeholder = Some(self.next_ty_var(TypeVariableOrigin {
-                    span: rustc_span::DUMMY_SP,
+                    span: DUMMY_SP,
                     kind: TypeVariableOriginKind::MiscVariable,
                 }));
                 if let Some(args) = args.make_suggestable(self.infcx.tcx, true, placeholder) {
@@ -584,7 +614,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             }
             InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
                 let placeholder = Some(self.next_ty_var(TypeVariableOrigin {
-                    span: rustc_span::DUMMY_SP,
+                    span: DUMMY_SP,
                     kind: TypeVariableOriginKind::MiscVariable,
                 }));
                 if let Some(ty) = ty.make_suggestable(self.infcx.tcx, true, placeholder) {
@@ -606,6 +636,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
+                was_written: path.as_ref().map(|_| ()),
+                path: path.unwrap_or_default(),
             }),
             TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
                 span,
@@ -615,6 +647,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
+                was_written: path.as_ref().map(|_| ()),
+                path: path.unwrap_or_default(),
             }),
             TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
                 span,
@@ -624,6 +658,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
+                was_written: path.as_ref().map(|_| ()),
+                path: path.unwrap_or_default(),
             }),
         }
     }
@@ -688,22 +724,23 @@ impl<'tcx> InferSource<'tcx> {
 }
 
 impl<'tcx> InferSourceKind<'tcx> {
-    fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String) {
+    fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String, Option<PathBuf>) {
+        let mut path = None;
         match *self {
             InferSourceKind::LetBinding { ty, .. }
             | InferSourceKind::ClosureArg { ty, .. }
             | InferSourceKind::ClosureReturn { ty, .. } => {
                 if ty.is_closure() {
-                    ("closure", closure_as_fn_str(infcx, ty))
+                    ("closure", closure_as_fn_str(infcx, ty), path)
                 } else if !ty.is_ty_or_numeric_infer() {
-                    ("normal", ty_to_string(infcx, ty, None))
+                    ("normal", infcx.tcx.short_ty_string(ty, &mut path), path)
                 } else {
-                    ("other", String::new())
+                    ("other", String::new(), path)
                 }
             }
             // FIXME: We should be able to add some additional info here.
             InferSourceKind::GenericArg { .. }
-            | InferSourceKind::FullyQualifiedMethodCall { .. } => ("other", String::new()),
+            | InferSourceKind::FullyQualifiedMethodCall { .. } => ("other", String::new(), path),
         }
     }
 }
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 16e3b8c11c1..b2403836397 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -105,7 +105,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
         BuiltinLintDiag::RedundantImport(spans, ident) => {
             for (span, is_imported) in spans {
                 let introduced = if is_imported { "imported" } else { "defined" };
-                let span_msg = if span.is_dummy() { "by prelude" } else { "here" };
+                let span_msg = if span.is_dummy() { "by the extern prelude" } else { "here" };
                 diag.span_label(
                     span,
                     format!("the item `{ident}` is already {introduced} {span_msg}"),
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 111a4fdcea1..503caa35358 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1074,10 +1074,14 @@ impl UnusedParens {
                 // Otherwise proceed with linting.
                 _ => {}
             }
-            let spans = inner
-                .span
-                .find_ancestor_inside(value.span)
-                .map(|inner| (value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())));
+            let spans = if !value.span.from_expansion() {
+                inner
+                    .span
+                    .find_ancestor_inside(value.span)
+                    .map(|inner| (value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())))
+            } else {
+                None
+            };
             self.emit_unused_delims(cx, value.span, spans, "pattern", keep_space, false);
         }
     }
@@ -1233,11 +1237,13 @@ impl EarlyLintPass for UnusedParens {
                         if self.with_self_ty_parens && b.generic_params.len() > 0 => {}
                     ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {}
                     _ => {
-                        let spans = r
-                            .span
-                            .find_ancestor_inside(ty.span)
-                            .map(|r| (ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())));
-
+                        let spans = if !ty.span.from_expansion() {
+                            r.span
+                                .find_ancestor_inside(ty.span)
+                                .map(|r| (ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
+                        } else {
+                            None
+                        };
                         self.emit_unused_delims(cx, ty.span, spans, "type", (false, false), false);
                     }
                 }
diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs
index 44ae72bcd26..d448c5338fc 100644
--- a/library/core/src/clone.rs
+++ b/library/core/src/clone.rs
@@ -227,13 +227,10 @@ mod impls {
     impl_clone! {
         usize u8 u16 u32 u64 u128
         isize i8 i16 i32 i64 i128
-        f32 f64
+        f16 f32 f64 f128
         bool char
     }
 
-    #[cfg(not(bootstrap))]
-    impl_clone! { f16 f128 }
-
     #[unstable(feature = "never_type", issue = "35121")]
     impl Clone for ! {
         #[inline]
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 81bba927554..fa218600ed9 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -1497,12 +1497,9 @@ mod impls {
     }
 
     partial_eq_impl! {
-        bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64
+        bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128
     }
 
-    #[cfg(not(bootstrap))]
-    partial_eq_impl! { f16 f128 }
-
     macro_rules! eq_impl {
         ($($t:ty)*) => ($(
             #[stable(feature = "rust1", since = "1.0.0")]
@@ -1553,10 +1550,7 @@ mod impls {
         }
     }
 
-    partial_ord_impl! { f32 f64 }
-
-    #[cfg(not(bootstrap))]
-    partial_ord_impl! { f16 f128 }
+    partial_ord_impl! { f16 f32 f64 f128 }
 
     macro_rules! ord_impl {
         ($($t:ty)*) => ($(
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index 0167d04c413..1737c631f0b 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -34,8 +34,10 @@ macro_rules! impl_float_to_int {
     }
 }
 
+impl_float_to_int!(f16 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
 impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
 impl_float_to_int!(f64 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
+impl_float_to_int!(f128 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
 
 // Conversion traits for primitive integer and float types
 // Conversions T -> T are covered by a blanket impl and therefore excluded
@@ -163,7 +165,12 @@ impl_from!(u16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0"
 impl_from!(u32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 
 // float -> float
+impl_from!(f16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+impl_from!(f16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+impl_from!(f16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 impl_from!(f32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+impl_from!(f32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+impl_from!(f64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
 
 macro_rules! impl_float_from_bool {
     ($float:ty) => {
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index dbdbaccb535..f4f33f8584b 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -517,8 +517,6 @@ impl CStr {
     /// # Examples
     ///
     /// ```
-    /// #![feature(cstr_count_bytes)]
-    ///
     /// use std::ffi::CStr;
     ///
     /// let cstr = CStr::from_bytes_with_nul(b"foo\0").unwrap();
@@ -530,7 +528,7 @@ impl CStr {
     #[inline]
     #[must_use]
     #[doc(alias("len", "strlen"))]
-    #[unstable(feature = "cstr_count_bytes", issue = "114441")]
+    #[stable(feature = "cstr_count_bytes", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "113219")]
     pub const fn count_bytes(&self) -> usize {
         self.inner.len() - 1
diff --git a/library/core/src/fmt/nofloat.rs b/library/core/src/fmt/nofloat.rs
index cfb94cd9de5..a36e7efcd95 100644
--- a/library/core/src/fmt/nofloat.rs
+++ b/library/core/src/fmt/nofloat.rs
@@ -11,5 +11,7 @@ macro_rules! floating {
     };
 }
 
+floating! { f16 }
 floating! { f32 }
 floating! { f64 }
+floating! { f128 }
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 0ba3a557a03..10d2698c5dd 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -200,8 +200,6 @@
 //
 // Language features:
 // tidy-alphabetical-start
-#![cfg_attr(not(bootstrap), feature(f128))]
-#![cfg_attr(not(bootstrap), feature(f16))]
 #![feature(abi_unadjusted)]
 #![feature(adt_const_params)]
 #![feature(allow_internal_unsafe)]
@@ -226,6 +224,8 @@
 #![feature(doc_notable_trait)]
 #![feature(effects)]
 #![feature(extern_types)]
+#![feature(f128)]
+#![feature(f16)]
 #![feature(freeze_impls)]
 #![feature(fundamental)]
 #![feature(generic_arg_infer)]
@@ -347,6 +347,10 @@ pub mod u8;
 #[path = "num/shells/usize.rs"]
 pub mod usize;
 
+#[path = "num/f128.rs"]
+pub mod f128;
+#[path = "num/f16.rs"]
+pub mod f16;
 #[path = "num/f32.rs"]
 pub mod f32;
 #[path = "num/f64.rs"]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index fb97b3bfa09..1d073a6d649 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -422,17 +422,11 @@ marker_impls! {
     Copy for
         usize, u8, u16, u32, u64, u128,
         isize, i8, i16, i32, i64, i128,
-        f32, f64,
+        f16, f32, f64, f128,
         bool, char,
         {T: ?Sized} *const T,
         {T: ?Sized} *mut T,
-}
 
-#[cfg(not(bootstrap))]
-marker_impls! {
-    #[stable(feature = "rust1", since = "1.0.0")]
-    Copy for
-        f16, f128,
 }
 
 #[unstable(feature = "never_type", issue = "35121")]
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
new file mode 100644
index 00000000000..3bc3e2dbf12
--- /dev/null
+++ b/library/core/src/num/f128.rs
@@ -0,0 +1,16 @@
+//! Constants for the `f128` quadruple-precision floating point type.
+//!
+//! *[See also the `f128` primitive type][f128].*
+//!
+//! Mathematically significant numbers are provided in the `consts` sub-module.
+//!
+//! For the constants defined directly in this module
+//! (as distinct from those defined in the `consts` sub-module),
+//! new code should instead use the associated constants
+//! defined directly on the `f128` type.
+
+#![unstable(feature = "f128", issue = "116909")]
+
+/// Basic mathematical constants.
+#[unstable(feature = "f128", issue = "116909")]
+pub mod consts {}
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
new file mode 100644
index 00000000000..969ebdc5690
--- /dev/null
+++ b/library/core/src/num/f16.rs
@@ -0,0 +1,16 @@
+//! Constants for the `f16` half-precision floating point type.
+//!
+//! *[See also the `f16` primitive type][f16].*
+//!
+//! Mathematically significant numbers are provided in the `consts` sub-module.
+//!
+//! For the constants defined directly in this module
+//! (as distinct from those defined in the `consts` sub-module),
+//! new code should instead use the associated constants
+//! defined directly on the `f16` type.
+
+#![unstable(feature = "f16", issue = "116909")]
+
+/// Basic mathematical constants.
+#[unstable(feature = "f16", issue = "116909")]
+pub mod consts {}
diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs
index fd50f804748..5e77788d8ea 100644
--- a/library/core/src/ops/arith.rs
+++ b/library/core/src/ops/arith.rs
@@ -109,7 +109,7 @@ macro_rules! add_impl {
     )*)
 }
 
-add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
+add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
 
 /// The subtraction operator `-`.
 ///
@@ -218,7 +218,7 @@ macro_rules! sub_impl {
     )*)
 }
 
-sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
+sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
 
 /// The multiplication operator `*`.
 ///
@@ -348,7 +348,7 @@ macro_rules! mul_impl {
     )*)
 }
 
-mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
+mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
 
 /// The division operator `/`.
 ///
@@ -506,7 +506,7 @@ macro_rules! div_impl_float {
     )*)
 }
 
-div_impl_float! { f32 f64 }
+div_impl_float! { f16 f32 f64 f128 }
 
 /// The remainder operator `%`.
 ///
@@ -623,7 +623,7 @@ macro_rules! rem_impl_float {
     )*)
 }
 
-rem_impl_float! { f32 f64 }
+rem_impl_float! { f16 f32 f64 f128 }
 
 /// The unary negation operator `-`.
 ///
@@ -698,7 +698,7 @@ macro_rules! neg_impl {
     )*)
 }
 
-neg_impl! { isize i8 i16 i32 i64 i128 f32 f64 }
+neg_impl! { isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
 
 /// The addition assignment operator `+=`.
 ///
@@ -765,7 +765,7 @@ macro_rules! add_assign_impl {
     )+)
 }
 
-add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
+add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
 
 /// The subtraction assignment operator `-=`.
 ///
@@ -832,7 +832,7 @@ macro_rules! sub_assign_impl {
     )+)
 }
 
-sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
+sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
 
 /// The multiplication assignment operator `*=`.
 ///
@@ -890,7 +890,7 @@ macro_rules! mul_assign_impl {
     )+)
 }
 
-mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
+mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
 
 /// The division assignment operator `/=`.
 ///
@@ -947,7 +947,7 @@ macro_rules! div_assign_impl {
     )+)
 }
 
-div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
+div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
 
 /// The remainder assignment operator `%=`.
 ///
@@ -1008,4 +1008,4 @@ macro_rules! rem_assign_impl {
     )+)
 }
 
-rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
+rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 15da4171bda..e8e23f2a7ec 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1074,7 +1074,22 @@ mod prim_tuple {}
 #[doc(hidden)]
 impl<T> (T,) {}
 
+#[rustc_doc_primitive = "f16"]
+#[doc(alias = "half")]
+/// A 16-bit floating point type (specifically, the "binary16" type defined in IEEE 754-2008).
+///
+/// This type is very similar to [`prim@f32`] but has decreased precision because it uses half as many
+/// bits. Please see [the documentation for [`prim@f32`] or [Wikipedia on
+/// half-precision values][wikipedia] for more information.
+///
+/// *[See also the `std::f16::consts` module](crate::f16::consts).*
+///
+/// [wikipedia]: https://en.wikipedia.org/wiki/Half-precision_floating-point_format
+#[unstable(feature = "f16", issue = "116909")]
+mod prim_f16 {}
+
 #[rustc_doc_primitive = "f32"]
+#[doc(alias = "single")]
 /// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
 ///
 /// This type can represent a wide range of decimal numbers, like `3.5`, `27`,
@@ -1143,6 +1158,7 @@ impl<T> (T,) {}
 mod prim_f32 {}
 
 #[rustc_doc_primitive = "f64"]
+#[doc(alias = "double")]
 /// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008).
 ///
 /// This type is very similar to [`f32`], but has increased
@@ -1157,6 +1173,20 @@ mod prim_f32 {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_f64 {}
 
+#[rustc_doc_primitive = "f128"]
+#[doc(alias = "quad")]
+/// A 128-bit floating point type (specifically, the "binary128" type defined in IEEE 754-2008).
+///
+/// This type is very similar to [`prim@f32`] and [`prim@f64`], but has increased precision by using twice
+/// as many bits as `f64`. Please see [the documentation for [`prim@f32`] or [Wikipedia on
+/// quad-precision values][wikipedia] for more information.
+///
+/// *[See also the `std::f128::consts` module](crate::f128::consts).*
+///
+/// [wikipedia]: https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
+#[unstable(feature = "f128", issue = "116909")]
+mod prim_f128 {}
+
 #[rustc_doc_primitive = "i8"]
 //
 /// The 8-bit signed integer type.
diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs
new file mode 100644
index 00000000000..4710d7c50b4
--- /dev/null
+++ b/library/std/src/f128.rs
@@ -0,0 +1,11 @@
+//! Constants for the `f128` double-precision floating point type.
+//!
+//! *[See also the `f128` primitive type](primitive@f128).*
+//!
+//! Mathematically significant numbers are provided in the `consts` sub-module.
+
+#[cfg(test)]
+mod tests;
+
+#[unstable(feature = "f128", issue = "116909")]
+pub use core::f128::consts;
diff --git a/library/std/src/f128/tests.rs b/library/std/src/f128/tests.rs
new file mode 100644
index 00000000000..b64c7f856a1
--- /dev/null
+++ b/library/std/src/f128/tests.rs
@@ -0,0 +1,40 @@
+#![allow(dead_code)] // FIXME(f16_f128): remove once constants are used
+
+/// Smallest number
+const TINY_BITS: u128 = 0x1;
+/// Next smallest number
+const TINY_UP_BITS: u128 = 0x2;
+/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
+const MAX_DOWN_BITS: u128 = 0x7ffeffffffffffffffffffffffffffff;
+/// Zeroed exponent, full significant
+const LARGEST_SUBNORMAL_BITS: u128 = 0x0000ffffffffffffffffffffffffffff;
+/// Exponent = 0b1, zeroed significand
+const SMALLEST_NORMAL_BITS: u128 = 0x00010000000000000000000000000000;
+/// First pattern over the mantissa
+const NAN_MASK1: u128 = 0x0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa;
+/// Second pattern over the mantissa
+const NAN_MASK2: u128 = 0x00005555555555555555555555555555;
+
+/// Compare by value
+#[allow(unused_macros)]
+macro_rules! assert_f128_eq {
+    ($a:expr, $b:expr) => {
+        let (l, r): (&f128, &f128) = (&$a, &$b);
+        assert_eq!(*l, *r, "\na: {:#0130x}\nb: {:#0130x}", l.to_bits(), r.to_bits())
+    };
+}
+
+/// Compare by representation
+#[allow(unused_macros)]
+macro_rules! assert_f128_biteq {
+    ($a:expr, $b:expr) => {
+        let (l, r): (&f128, &f128) = (&$a, &$b);
+        let lb = l.to_bits();
+        let rb = r.to_bits();
+        assert_eq!(
+            lb, rb,
+            "float {:?} is not bitequal to {:?}.\na: {:#0130x}\nb: {:#0130x}",
+            *l, *r, lb, rb
+        );
+    };
+}
diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs
new file mode 100644
index 00000000000..c36f9f5d4c6
--- /dev/null
+++ b/library/std/src/f16.rs
@@ -0,0 +1,11 @@
+//! Constants for the `f16` double-precision floating point type.
+//!
+//! *[See also the `f16` primitive type](primitive@f16).*
+//!
+//! Mathematically significant numbers are provided in the `consts` sub-module.
+
+#[cfg(test)]
+mod tests;
+
+#[unstable(feature = "f16", issue = "116909")]
+pub use core::f16::consts;
diff --git a/library/std/src/f16/tests.rs b/library/std/src/f16/tests.rs
new file mode 100644
index 00000000000..d65c43eca4b
--- /dev/null
+++ b/library/std/src/f16/tests.rs
@@ -0,0 +1,46 @@
+#![allow(dead_code)] // FIXME(f16_f128): remove once constants are used
+
+// We run out of precision pretty quickly with f16
+const F16_APPROX_L1: f16 = 0.001;
+const F16_APPROX_L2: f16 = 0.01;
+const F16_APPROX_L3: f16 = 0.1;
+const F16_APPROX_L4: f16 = 0.5;
+
+/// Smallest number
+const TINY_BITS: u16 = 0x1;
+/// Next smallest number
+const TINY_UP_BITS: u16 = 0x2;
+/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
+const MAX_DOWN_BITS: u16 = 0x7bfe;
+/// Zeroed exponent, full significant
+const LARGEST_SUBNORMAL_BITS: u16 = 0x03ff;
+/// Exponent = 0b1, zeroed significand
+const SMALLEST_NORMAL_BITS: u16 = 0x0400;
+/// First pattern over the mantissa
+const NAN_MASK1: u16 = 0x02aa;
+/// Second pattern over the mantissa
+const NAN_MASK2: u16 = 0x0155;
+
+/// Compare by value
+#[allow(unused_macros)]
+macro_rules! assert_f16_eq {
+    ($a:expr, $b:expr) => {
+        let (l, r): (&f16, &f16) = (&$a, &$b);
+        assert_eq!(*l, *r, "\na: {:#018x}\nb: {:#018x}", l.to_bits(), r.to_bits())
+    };
+}
+
+/// Compare by representation
+#[allow(unused_macros)]
+macro_rules! assert_f16_biteq {
+    ($a:expr, $b:expr) => {
+        let (l, r): (&f16, &f16) = (&$a, &$b);
+        let lb = l.to_bits();
+        let rb = r.to_bits();
+        assert_eq!(
+            lb, rb,
+            "float {:?} is not bitequal to {:?}.\na: {:#018x}\nb: {:#018x}",
+            *l, *r, lb, rb
+        );
+    };
+}
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index b1102b440e0..1b8fafd0089 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -465,14 +465,20 @@ impl File {
         OpenOptions::new()
     }
 
-    /// Attempts to sync all OS-internal metadata to disk.
+    /// Attempts to sync all OS-internal file content and metadata to disk.
     ///
     /// This function will attempt to ensure that all in-memory data reaches the
     /// filesystem before returning.
     ///
     /// This can be used to handle errors that would otherwise only be caught
-    /// when the `File` is closed.  Dropping a file will ignore errors in
-    /// synchronizing this in-memory data.
+    /// when the `File` is closed, as dropping a `File` will ignore all errors.
+    /// Note, however, that `sync_all` is generally more expensive than closing
+    /// a file by dropping it, because the latter is not required to block until
+    /// the data has been written to the filesystem.
+    ///
+    /// If synchronizing the metadata is not required, use [`sync_data`] instead.
+    ///
+    /// [`sync_data`]: File::sync_data
     ///
     /// # Examples
     ///
@@ -489,6 +495,7 @@ impl File {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[doc(alias = "fsync")]
     pub fn sync_all(&self) -> io::Result<()> {
         self.inner.fsync()
     }
@@ -520,6 +527,7 @@ impl File {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[doc(alias = "fdatasync")]
     pub fn sync_data(&self) -> io::Result<()> {
         self.inner.datasync()
     }
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index c713eefc72c..ac475b5530a 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -214,7 +214,16 @@
 //! [slice]: prim@slice
 
 #![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
-#![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
+#![cfg_attr(
+    feature = "restricted-std",
+    unstable(
+        feature = "restricted_std",
+        issue = "none",
+        reason = "You have attempted to use a standard library built for a platform that it doesn't \
+            know how to support. Consider building it for a known environment, disabling it with \
+            `#![no_std]` or overriding this warning by enabling this feature".
+    )
+)]
 #![cfg_attr(not(bootstrap), rustc_preserve_ub_checks)]
 #![doc(
     html_playground_url = "https://play.rust-lang.org/",
@@ -283,6 +292,8 @@
 #![feature(doc_masked)]
 #![feature(doc_notable_trait)]
 #![feature(dropck_eyepatch)]
+#![feature(f128)]
+#![feature(f16)]
 #![feature(if_let_guard)]
 #![feature(intra_doc_pointers)]
 #![feature(lang_items)]
@@ -558,6 +569,10 @@ pub use core::u8;
 #[allow(deprecated, deprecated_in_future)]
 pub use core::usize;
 
+#[unstable(feature = "f128", issue = "116909")]
+pub mod f128;
+#[unstable(feature = "f16", issue = "116909")]
+pub mod f16;
 pub mod f32;
 pub mod f64;
 
diff --git a/tests/codegen/float/f128.rs b/tests/codegen/float/f128.rs
new file mode 100644
index 00000000000..97d545e0283
--- /dev/null
+++ b/tests/codegen/float/f128.rs
@@ -0,0 +1,129 @@
+// Verify that our intrinsics generate the correct LLVM calls for f128
+
+#![crate_type = "lib"]
+#![feature(f128)]
+#![feature(core_intrinsics)]
+
+// CHECK-LABEL: i1 @f128_eq(
+#[no_mangle]
+pub fn f128_eq(a: f128, b: f128) -> bool {
+    // CHECK: fcmp oeq fp128 %{{.+}}, %{{.+}}
+    a == b
+}
+
+// CHECK-LABEL: i1 @f128_ne(
+#[no_mangle]
+pub fn f128_ne(a: f128, b: f128) -> bool {
+    // CHECK: fcmp une fp128 %{{.+}}, %{{.+}}
+    a != b
+}
+
+// CHECK-LABEL: i1 @f128_gt(
+#[no_mangle]
+pub fn f128_gt(a: f128, b: f128) -> bool {
+    // CHECK: fcmp ogt fp128 %{{.+}}, %{{.+}}
+    a > b
+}
+
+// CHECK-LABEL: i1 @f128_ge(
+#[no_mangle]
+pub fn f128_ge(a: f128, b: f128) -> bool {
+    // CHECK: fcmp oge fp128 %{{.+}}, %{{.+}}
+    a >= b
+}
+
+// CHECK-LABEL: i1 @f128_lt(
+#[no_mangle]
+pub fn f128_lt(a: f128, b: f128) -> bool {
+    // CHECK: fcmp olt fp128 %{{.+}}, %{{.+}}
+    a < b
+}
+
+// CHECK-LABEL: i1 @f128_le(
+#[no_mangle]
+pub fn f128_le(a: f128, b: f128) -> bool {
+    // CHECK: fcmp ole fp128 %{{.+}}, %{{.+}}
+    a <= b
+}
+
+// CHECK-LABEL: fp128 @f128_neg(
+#[no_mangle]
+pub fn f128_neg(a: f128) -> f128 {
+    // CHECK: fneg fp128
+    -a
+}
+
+// CHECK-LABEL: fp128 @f128_add(
+#[no_mangle]
+pub fn f128_add(a: f128, b: f128) -> f128 {
+    // CHECK: fadd fp128 %{{.+}}, %{{.+}}
+    a + b
+}
+
+// CHECK-LABEL: fp128 @f128_sub(
+#[no_mangle]
+pub fn f128_sub(a: f128, b: f128) -> f128 {
+    // CHECK: fsub fp128 %{{.+}}, %{{.+}}
+    a - b
+}
+
+// CHECK-LABEL: fp128 @f128_mul(
+#[no_mangle]
+pub fn f128_mul(a: f128, b: f128) -> f128 {
+    // CHECK: fmul fp128 %{{.+}}, %{{.+}}
+    a * b
+}
+
+// CHECK-LABEL: fp128 @f128_div(
+#[no_mangle]
+pub fn f128_div(a: f128, b: f128) -> f128 {
+    // CHECK: fdiv fp128 %{{.+}}, %{{.+}}
+    a / b
+}
+
+// CHECK-LABEL: fp128 @f128_rem(
+#[no_mangle]
+pub fn f128_rem(a: f128, b: f128) -> f128 {
+    // CHECK: frem fp128 %{{.+}}, %{{.+}}
+    a % b
+}
+
+// CHECK-LABEL: void @f128_add_assign(
+#[no_mangle]
+pub fn f128_add_assign(a: &mut f128, b: f128) {
+    // CHECK: fadd fp128 %{{.+}}, %{{.+}}
+    // CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
+    *a += b;
+}
+
+// CHECK-LABEL: void @f128_sub_assign(
+#[no_mangle]
+pub fn f128_sub_assign(a: &mut f128, b: f128) {
+    // CHECK: fsub fp128 %{{.+}}, %{{.+}}
+    // CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
+    *a -= b;
+}
+
+// CHECK-LABEL: void @f128_mul_assign(
+#[no_mangle]
+pub fn f128_mul_assign(a: &mut f128, b: f128) {
+    // CHECK: fmul fp128 %{{.+}}, %{{.+}}
+    // CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
+    *a *= b
+}
+
+// CHECK-LABEL: void @f128_div_assign(
+#[no_mangle]
+pub fn f128_div_assign(a: &mut f128, b: f128) {
+    // CHECK: fdiv fp128 %{{.+}}, %{{.+}}
+    // CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
+    *a /= b
+}
+
+// CHECK-LABEL: void @f128_rem_assign(
+#[no_mangle]
+pub fn f128_rem_assign(a: &mut f128, b: f128) {
+    // CHECK: frem fp128 %{{.+}}, %{{.+}}
+    // CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
+    *a %= b
+}
diff --git a/tests/codegen/float/f16.rs b/tests/codegen/float/f16.rs
new file mode 100644
index 00000000000..d1f75cc3b68
--- /dev/null
+++ b/tests/codegen/float/f16.rs
@@ -0,0 +1,129 @@
+// Verify that our intrinsics generate the correct LLVM calls for f16
+
+#![crate_type = "lib"]
+#![feature(f16)]
+#![feature(core_intrinsics)]
+
+// CHECK-LABEL: i1 @f16_eq(
+#[no_mangle]
+pub fn f16_eq(a: f16, b: f16) -> bool {
+    // CHECK: fcmp oeq half %{{.+}}, %{{.+}}
+    a == b
+}
+
+// CHECK-LABEL: i1 @f16_ne(
+#[no_mangle]
+pub fn f16_ne(a: f16, b: f16) -> bool {
+    // CHECK: fcmp une half %{{.+}}, %{{.+}}
+    a != b
+}
+
+// CHECK-LABEL: i1 @f16_gt(
+#[no_mangle]
+pub fn f16_gt(a: f16, b: f16) -> bool {
+    // CHECK: fcmp ogt half %{{.+}}, %{{.+}}
+    a > b
+}
+
+// CHECK-LABEL: i1 @f16_ge(
+#[no_mangle]
+pub fn f16_ge(a: f16, b: f16) -> bool {
+    // CHECK: fcmp oge half %{{.+}}, %{{.+}}
+    a >= b
+}
+
+// CHECK-LABEL: i1 @f16_lt(
+#[no_mangle]
+pub fn f16_lt(a: f16, b: f16) -> bool {
+    // CHECK: fcmp olt half %{{.+}}, %{{.+}}
+    a < b
+}
+
+// CHECK-LABEL: i1 @f16_le(
+#[no_mangle]
+pub fn f16_le(a: f16, b: f16) -> bool {
+    // CHECK: fcmp ole half %{{.+}}, %{{.+}}
+    a <= b
+}
+
+// CHECK-LABEL: half @f16_neg(
+#[no_mangle]
+pub fn f16_neg(a: f16) -> f16 {
+    // CHECK: fneg half %{{.+}}
+    -a
+}
+
+// CHECK-LABEL: half @f16_add(
+#[no_mangle]
+pub fn f16_add(a: f16, b: f16) -> f16 {
+    // CHECK: fadd half %{{.+}}, %{{.+}}
+    a + b
+}
+
+// CHECK-LABEL: half @f16_sub(
+#[no_mangle]
+pub fn f16_sub(a: f16, b: f16) -> f16 {
+    // CHECK: fsub half %{{.+}}, %{{.+}}
+    a - b
+}
+
+// CHECK-LABEL: half @f16_mul(
+#[no_mangle]
+pub fn f16_mul(a: f16, b: f16) -> f16 {
+    // CHECK: fmul half %{{.+}}, %{{.+}}
+    a * b
+}
+
+// CHECK-LABEL: half @f16_div(
+#[no_mangle]
+pub fn f16_div(a: f16, b: f16) -> f16 {
+    // CHECK: fdiv half %{{.+}}, %{{.+}}
+    a / b
+}
+
+// CHECK-LABEL: half @f16_rem(
+#[no_mangle]
+pub fn f16_rem(a: f16, b: f16) -> f16 {
+    // CHECK: frem half %{{.+}}, %{{.+}}
+    a % b
+}
+
+// CHECK-LABEL: void @f16_add_assign(
+#[no_mangle]
+pub fn f16_add_assign(a: &mut f16, b: f16) {
+    // CHECK: fadd half %{{.+}}, %{{.+}}
+    // CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
+    *a += b;
+}
+
+// CHECK-LABEL: void @f16_sub_assign(
+#[no_mangle]
+pub fn f16_sub_assign(a: &mut f16, b: f16) {
+    // CHECK: fsub half %{{.+}}, %{{.+}}
+    // CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
+    *a -= b;
+}
+
+// CHECK-LABEL: void @f16_mul_assign(
+#[no_mangle]
+pub fn f16_mul_assign(a: &mut f16, b: f16) {
+    // CHECK: fmul half %{{.+}}, %{{.+}}
+    // CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
+    *a *= b
+}
+
+// CHECK-LABEL: void @f16_div_assign(
+#[no_mangle]
+pub fn f16_div_assign(a: &mut f16, b: f16) {
+    // CHECK: fdiv half %{{.+}}, %{{.+}}
+    // CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
+    *a /= b
+}
+
+// CHECK-LABEL: void @f16_rem_assign(
+#[no_mangle]
+pub fn f16_rem_assign(a: &mut f16, b: f16) {
+    // CHECK: frem half %{{.+}}, %{{.+}}
+    // CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
+    *a %= b
+}
diff --git a/tests/ui/array-slice-vec/vector-no-ann.stderr b/tests/ui/array-slice-vec/vector-no-ann.stderr
index 24b6abfb342..716971eb120 100644
--- a/tests/ui/array-slice-vec/vector-no-ann.stderr
+++ b/tests/ui/array-slice-vec/vector-no-ann.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Vec<T>`
+error[E0282]: type annotations needed for `Vec<_>`
   --> $DIR/vector-no-ann.rs:2:9
    |
 LL |     let _foo = Vec::new();
diff --git a/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr b/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr
index 92f38d5a796..640d946421a 100644
--- a/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr
+++ b/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr
@@ -62,7 +62,7 @@ error[E0308]: mismatched types
   --> $DIR/async-closure-gate.rs:27:5
    |
 LL |   fn foo3() {
-   |            - help: a return type might be missing here: `-> _`
+   |            - help: try adding a return type: `-> impl Future<Output = ()>`
 LL | /     async {
 LL | |
 LL | |         let _ = #[track_caller] || {
@@ -78,7 +78,7 @@ error[E0308]: mismatched types
   --> $DIR/async-closure-gate.rs:44:5
    |
 LL |   fn foo5() {
-   |            - help: a return type might be missing here: `-> _`
+   |            - help: try adding a return type: `-> impl Future<Output = ()>`
 LL | /     async {
 LL | |
 LL | |         let _ = || {
diff --git a/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr b/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr
index 92f38d5a796..640d946421a 100644
--- a/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr
+++ b/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr
@@ -62,7 +62,7 @@ error[E0308]: mismatched types
   --> $DIR/async-closure-gate.rs:27:5
    |
 LL |   fn foo3() {
-   |            - help: a return type might be missing here: `-> _`
+   |            - help: try adding a return type: `-> impl Future<Output = ()>`
 LL | /     async {
 LL | |
 LL | |         let _ = #[track_caller] || {
@@ -78,7 +78,7 @@ error[E0308]: mismatched types
   --> $DIR/async-closure-gate.rs:44:5
    |
 LL |   fn foo5() {
-   |            - help: a return type might be missing here: `-> _`
+   |            - help: try adding a return type: `-> impl Future<Output = ()>`
 LL | /     async {
 LL | |
 LL | |         let _ = || {
diff --git a/tests/ui/const-generics/defaults/doesnt_infer.rs b/tests/ui/const-generics/defaults/doesnt_infer.rs
index 9c59e672d8e..e14c08fc148 100644
--- a/tests/ui/const-generics/defaults/doesnt_infer.rs
+++ b/tests/ui/const-generics/defaults/doesnt_infer.rs
@@ -9,5 +9,5 @@ impl<const N: u32> Foo<N> {
 fn main() {
     let foo = Foo::<1>::foo();
     let foo = Foo::foo();
-    //~^ error: type annotations needed for `Foo<N>`
+    //~^ ERROR type annotations needed for `Foo<_>`
 }
diff --git a/tests/ui/const-generics/defaults/doesnt_infer.stderr b/tests/ui/const-generics/defaults/doesnt_infer.stderr
index 65ee0ecfdc5..93d58603397 100644
--- a/tests/ui/const-generics/defaults/doesnt_infer.stderr
+++ b/tests/ui/const-generics/defaults/doesnt_infer.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Foo<N>`
+error[E0282]: type annotations needed for `Foo<_>`
   --> $DIR/doesnt_infer.rs:11:9
    |
 LL |     let foo = Foo::foo();
diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr
index 5b296a14869..5ee42c19dd3 100644
--- a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr
+++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr
@@ -1,4 +1,4 @@
-error[E0283]: type annotations needed for `Mask<_, N>`
+error[E0283]: type annotations needed for `Mask<_, _>`
   --> $DIR/issue-91614.rs:6:9
    |
 LL |     let y = Mask::<_, _>::splat(false);
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr
index f27d52a1437..5cda4681b5c 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr
@@ -18,7 +18,7 @@ help: try adding a `where` bound
 LL |     pub const fn new() -> Self where [(); Self::SIZE]: {
    |                                +++++++++++++++++++++++
 
-error[E0282]: type annotations needed for `ArrayHolder<X>`
+error[E0282]: type annotations needed for `ArrayHolder<_>`
   --> $DIR/issue-62504.rs:26:9
    |
 LL |     let mut array = ArrayHolder::new();
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr
index 1664669eee0..beb159779ff 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr
@@ -22,7 +22,7 @@ note: tuple struct defined here
 LL | struct ArrayHolder<const X: usize>([u32; X]);
    |        ^^^^^^^^^^^
 
-error[E0282]: type annotations needed for `ArrayHolder<X>`
+error[E0282]: type annotations needed for `ArrayHolder<_>`
   --> $DIR/issue-62504.rs:26:9
    |
 LL |     let mut array = ArrayHolder::new();
diff --git a/tests/ui/generic-const-items/inference-failure.stderr b/tests/ui/generic-const-items/inference-failure.stderr
index 10ecd83ec53..594743a47f4 100644
--- a/tests/ui/generic-const-items/inference-failure.stderr
+++ b/tests/ui/generic-const-items/inference-failure.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Option<T>`
+error[E0282]: type annotations needed for `Option<_>`
   --> $DIR/inference-failure.rs:8:9
    |
 LL |     let _ = NONE;
diff --git a/tests/ui/generic-const-items/parameter-defaults.stderr b/tests/ui/generic-const-items/parameter-defaults.stderr
index b8220af5d0e..13562c98f6d 100644
--- a/tests/ui/generic-const-items/parameter-defaults.stderr
+++ b/tests/ui/generic-const-items/parameter-defaults.stderr
@@ -4,7 +4,7 @@ error: defaults for type parameters are only allowed in `struct`, `enum`, `type`
 LL | const NONE<T = ()>: Option<T> = None::<T>;
    |            ^^^^^^
 
-error[E0282]: type annotations needed for `Option<T>`
+error[E0282]: type annotations needed for `Option<_>`
   --> $DIR/parameter-defaults.rs:13:9
    |
 LL |     let _ = NONE;
diff --git a/tests/ui/imports/redundant-import-extern-prelude.rs b/tests/ui/imports/redundant-import-extern-prelude.rs
new file mode 100644
index 00000000000..acf59b09a1d
--- /dev/null
+++ b/tests/ui/imports/redundant-import-extern-prelude.rs
@@ -0,0 +1,17 @@
+// Check that we detect imports that are redundant due to the extern prelude
+// and that we emit a reasonable diagnostic.
+// issue: rust-lang/rust#121915
+//~^^^ NOTE the item `aux_issue_121915` is already defined by the extern prelude
+
+// See also the discussion in <https://github.com/rust-lang/rust/pull/122954>.
+
+//@ compile-flags: --extern aux_issue_121915 --edition 2018
+//@ aux-build: aux-issue-121915.rs
+
+#[deny(unused_imports)]
+//~^ NOTE the lint level is defined here
+fn main() {
+    use aux_issue_121915;
+    //~^ ERROR the item `aux_issue_121915` is imported redundantly
+    aux_issue_121915::item();
+}
diff --git a/tests/ui/imports/redundant-import-issue-121915.stderr b/tests/ui/imports/redundant-import-extern-prelude.stderr
index 0047d7c3420..d49e013c3d3 100644
--- a/tests/ui/imports/redundant-import-issue-121915.stderr
+++ b/tests/ui/imports/redundant-import-extern-prelude.stderr
@@ -1,11 +1,11 @@
 error: the item `aux_issue_121915` is imported redundantly
-  --> $DIR/redundant-import-issue-121915.rs:6:9
+  --> $DIR/redundant-import-extern-prelude.rs:14:9
    |
 LL |     use aux_issue_121915;
-   |         ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by prelude
+   |         ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by the extern prelude
    |
 note: the lint level is defined here
-  --> $DIR/redundant-import-issue-121915.rs:4:8
+  --> $DIR/redundant-import-extern-prelude.rs:11:8
    |
 LL | #[deny(unused_imports)]
    |        ^^^^^^^^^^^^^^
diff --git a/tests/ui/imports/redundant-import-issue-121915.rs b/tests/ui/imports/redundant-import-issue-121915.rs
deleted file mode 100644
index 237acc4af25..00000000000
--- a/tests/ui/imports/redundant-import-issue-121915.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ compile-flags: --extern aux_issue_121915 --edition 2018
-//@ aux-build: aux-issue-121915.rs
-
-#[deny(unused_imports)]
-fn main() {
-    use aux_issue_121915;
-    //~^ ERROR the item `aux_issue_121915` is imported redundantly
-    aux_issue_121915::item();
-}
diff --git a/tests/ui/imports/redundant-import-lang-prelude-attr.rs b/tests/ui/imports/redundant-import-lang-prelude-attr.rs
new file mode 100644
index 00000000000..18d0e688206
--- /dev/null
+++ b/tests/ui/imports/redundant-import-lang-prelude-attr.rs
@@ -0,0 +1,18 @@
+// Check that we detect imports (of built-in attributes) that are redundant due to
+// the language prelude and that we emit a reasonable diagnostic.
+//~^^ NOTE the item `allow` is already defined by the extern prelude
+
+// Note that we use the term "extern prelude" in the label even though "language prelude"
+// would be more correct. However, it's not worth special-casing this.
+
+// See also the discussion in <https://github.com/rust-lang/rust/pull/122954>.
+
+//@ edition: 2018
+
+#![deny(unused_imports)]
+//~^ NOTE the lint level is defined here
+
+use allow; //~ ERROR the item `allow` is imported redundantly
+
+#[allow(unused)]
+fn main() {}
diff --git a/tests/ui/imports/redundant-import-lang-prelude-attr.stderr b/tests/ui/imports/redundant-import-lang-prelude-attr.stderr
new file mode 100644
index 00000000000..a3ca7ce24ed
--- /dev/null
+++ b/tests/ui/imports/redundant-import-lang-prelude-attr.stderr
@@ -0,0 +1,14 @@
+error: the item `allow` is imported redundantly
+  --> $DIR/redundant-import-lang-prelude-attr.rs:15:5
+   |
+LL | use allow;
+   |     ^^^^^ the item `allow` is already defined by the extern prelude
+   |
+note: the lint level is defined here
+  --> $DIR/redundant-import-lang-prelude-attr.rs:12:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/imports/redundant-import-lang-prelude.rs b/tests/ui/imports/redundant-import-lang-prelude.rs
new file mode 100644
index 00000000000..3faf9423c37
--- /dev/null
+++ b/tests/ui/imports/redundant-import-lang-prelude.rs
@@ -0,0 +1,18 @@
+// Check that we detect imports that are redundant due to the language prelude
+// and that we emit a reasonable diagnostic.
+//~^^ NOTE the item `u8` is already defined by the extern prelude
+
+// Note that we use the term "extern prelude" in the label even though "language prelude"
+// would be more correct. However, it's not worth special-casing this.
+
+// See also the discussion in <https://github.com/rust-lang/rust/pull/122954>.
+
+#![deny(unused_imports)]
+//~^ NOTE the lint level is defined here
+
+use std::primitive::u8;
+//~^ ERROR the item `u8` is imported redundantly
+
+const _: u8 = 0;
+
+fn main() {}
diff --git a/tests/ui/imports/redundant-import-lang-prelude.stderr b/tests/ui/imports/redundant-import-lang-prelude.stderr
new file mode 100644
index 00000000000..e6a4535f980
--- /dev/null
+++ b/tests/ui/imports/redundant-import-lang-prelude.stderr
@@ -0,0 +1,14 @@
+error: the item `u8` is imported redundantly
+  --> $DIR/redundant-import-lang-prelude.rs:13:5
+   |
+LL | use std::primitive::u8;
+   |     ^^^^^^^^^^^^^^^^^^ the item `u8` is already defined by the extern prelude
+   |
+note: the lint level is defined here
+  --> $DIR/redundant-import-lang-prelude.rs:10:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/imports/redundant-import-undetected-macro-use-prelude.rs b/tests/ui/imports/redundant-import-undetected-macro-use-prelude.rs
new file mode 100644
index 00000000000..4a79cb2c208
--- /dev/null
+++ b/tests/ui/imports/redundant-import-undetected-macro-use-prelude.rs
@@ -0,0 +1,23 @@
+// This test demonstrates that we currently don't make an effort to detect
+// imports made redundant by the `#[macro_use]` prelude.
+// See also the discussion in <https://github.com/rust-lang/rust/pull/122954>.
+
+//@ check-pass
+//@ aux-build:two_macros.rs
+#![deny(unused_imports)]
+
+#[macro_use]
+extern crate two_macros;
+
+// This import is actually redundant due to the `#[macro_use]` above.
+use two_macros::n;
+
+// We intentionally reference two items from the `#[macro_use]`'d crate because
+// if we were to reference only item `n`, we would flag the `#[macro_use]`
+// attribute as redundant which would be correct of course.
+// That's interesting on its own -- we prefer "blaming" the `#[macro_use]`
+// over the import (here, `use two_macros::n`) when it comes to redundancy.
+n!();
+m!();
+
+fn main() {}
diff --git a/tests/ui/inference/cannot-infer-closure-circular.rs b/tests/ui/inference/cannot-infer-closure-circular.rs
index affb481496d..1b41171e74a 100644
--- a/tests/ui/inference/cannot-infer-closure-circular.rs
+++ b/tests/ui/inference/cannot-infer-closure-circular.rs
@@ -4,7 +4,7 @@ fn main() {
     // error handles this gracefully, and in particular doesn't generate an extra
     // note about the `?` operator in the closure body, which isn't relevant to
     // the inference.
-    let x = |r| { //~ ERROR type annotations needed for `Result<(), E>`
+    let x = |r| { //~ ERROR type annotations needed for `Result<(), _>`
         let v = r?;
         Ok(v)
     };
diff --git a/tests/ui/inference/cannot-infer-closure-circular.stderr b/tests/ui/inference/cannot-infer-closure-circular.stderr
index e3cf0cca837..a16e832f8ef 100644
--- a/tests/ui/inference/cannot-infer-closure-circular.stderr
+++ b/tests/ui/inference/cannot-infer-closure-circular.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Result<(), E>`
+error[E0282]: type annotations needed for `Result<(), _>`
   --> $DIR/cannot-infer-closure-circular.rs:7:14
    |
 LL |     let x = |r| {
diff --git a/tests/ui/inference/erase-type-params-in-label.stderr b/tests/ui/inference/erase-type-params-in-label.stderr
index 546e679f2d0..4e9a74c1e40 100644
--- a/tests/ui/inference/erase-type-params-in-label.stderr
+++ b/tests/ui/inference/erase-type-params-in-label.stderr
@@ -1,4 +1,4 @@
-error[E0283]: type annotations needed for `Foo<i32, &str, W, Z>`
+error[E0283]: type annotations needed for `Foo<i32, &str, _, _>`
   --> $DIR/erase-type-params-in-label.rs:2:9
    |
 LL |     let foo = foo(1, "");
@@ -15,7 +15,7 @@ help: consider giving `foo` an explicit type, where the type for type parameter
 LL |     let foo: Foo<i32, &str, W, Z> = foo(1, "");
    |            ++++++++++++++++++++++
 
-error[E0283]: type annotations needed for `Bar<i32, &str, Z>`
+error[E0283]: type annotations needed for `Bar<i32, &str, _>`
   --> $DIR/erase-type-params-in-label.rs:5:9
    |
 LL |     let bar = bar(1, "");
diff --git a/tests/ui/inference/issue-104649.stderr b/tests/ui/inference/issue-104649.stderr
index afece960914..391ed16f349 100644
--- a/tests/ui/inference/issue-104649.stderr
+++ b/tests/ui/inference/issue-104649.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `A<std::result::Result<std::result::Result<(), E>, Error>>`
+error[E0282]: type annotations needed for `A<std::result::Result<std::result::Result<(), _>, Error>>`
   --> $DIR/issue-104649.rs:24:9
    |
 LL |     let a = A(Result::Ok(Result::Ok(())));
diff --git a/tests/ui/inference/issue-72690.stderr b/tests/ui/inference/issue-72690.stderr
index 6c93241ea07..6391672f861 100644
--- a/tests/ui/inference/issue-72690.stderr
+++ b/tests/ui/inference/issue-72690.stderr
@@ -50,7 +50,7 @@ help: try using a fully qualified path to specify the expected types
 LL |     |x| String::from(<str as AsRef<T>>::as_ref("x"));
    |                      ++++++++++++++++++++++++++   ~
 
-error[E0283]: type annotations needed for `&T`
+error[E0283]: type annotations needed for `&_`
   --> $DIR/issue-72690.rs:17:9
    |
 LL |     let _ = "x".as_ref();
diff --git a/tests/ui/inference/issue-83606.rs b/tests/ui/inference/issue-83606.rs
index c387046e910..4454b5e60f0 100644
--- a/tests/ui/inference/issue-83606.rs
+++ b/tests/ui/inference/issue-83606.rs
@@ -6,5 +6,5 @@ fn foo<const N: usize>(_: impl std::fmt::Display) -> [usize; N] {
 
 fn main() {
     let _ = foo("foo");
-    //~^ ERROR: type annotations needed for `[usize; N]`
+    //~^ ERROR type annotations needed for `[usize; _]`
 }
diff --git a/tests/ui/inference/issue-83606.stderr b/tests/ui/inference/issue-83606.stderr
index 00de4029e42..8e6ff6d568d 100644
--- a/tests/ui/inference/issue-83606.stderr
+++ b/tests/ui/inference/issue-83606.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `[usize; N]`
+error[E0282]: type annotations needed for `[usize; _]`
   --> $DIR/issue-83606.rs:8:9
    |
 LL |     let _ = foo("foo");
diff --git a/tests/ui/issues/issue-11771.stderr b/tests/ui/issues/issue-11771.stderr
index 161fce4b031..d4a4647f6a1 100644
--- a/tests/ui/issues/issue-11771.stderr
+++ b/tests/ui/issues/issue-11771.stderr
@@ -6,15 +6,15 @@ LL |     1 +
    |
    = help: the trait `Add<()>` is not implemented for `{integer}`
    = help: the following other types implement trait `Add<Rhs>`:
+             <&'a f128 as Add<f128>>
+             <&'a f16 as Add<f16>>
              <&'a f32 as Add<f32>>
              <&'a f64 as Add<f64>>
              <&'a i128 as Add<i128>>
              <&'a i16 as Add<i16>>
              <&'a i32 as Add<i32>>
              <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+           and 56 others
 
 error[E0277]: cannot add `()` to `{integer}`
   --> $DIR/issue-11771.rs:8:7
@@ -24,15 +24,15 @@ LL |     1 +
    |
    = help: the trait `Add<()>` is not implemented for `{integer}`
    = help: the following other types implement trait `Add<Rhs>`:
+             <&'a f128 as Add<f128>>
+             <&'a f16 as Add<f16>>
              <&'a f32 as Add<f32>>
              <&'a f64 as Add<f64>>
              <&'a i128 as Add<i128>>
              <&'a i16 as Add<i16>>
              <&'a i32 as Add<i32>>
              <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+           and 56 others
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/issues/issue-12187-1.stderr b/tests/ui/issues/issue-12187-1.stderr
index 93dc1df8f63..704854fe585 100644
--- a/tests/ui/issues/issue-12187-1.stderr
+++ b/tests/ui/issues/issue-12187-1.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `&T`
+error[E0282]: type annotations needed for `&_`
   --> $DIR/issue-12187-1.rs:6:9
    |
 LL |     let &v = new();
diff --git a/tests/ui/issues/issue-12187-2.stderr b/tests/ui/issues/issue-12187-2.stderr
index e9ba52ff4fd..eeef63a1d0b 100644
--- a/tests/ui/issues/issue-12187-2.stderr
+++ b/tests/ui/issues/issue-12187-2.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `&T`
+error[E0282]: type annotations needed for `&_`
   --> $DIR/issue-12187-2.rs:6:9
    |
 LL |     let &v = new();
diff --git a/tests/ui/issues/issue-17551.stderr b/tests/ui/issues/issue-17551.stderr
index 68f54a31084..b9cb76fc298 100644
--- a/tests/ui/issues/issue-17551.stderr
+++ b/tests/ui/issues/issue-17551.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `B<T>`
+error[E0282]: type annotations needed for `B<_>`
   --> $DIR/issue-17551.rs:6:9
    |
 LL |     let foo = B(marker::PhantomData);
diff --git a/tests/ui/issues/issue-23046.stderr b/tests/ui/issues/issue-23046.stderr
index b6e23814543..f70ac0c9f38 100644
--- a/tests/ui/issues/issue-23046.stderr
+++ b/tests/ui/issues/issue-23046.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Expr<'_, VAR>`
+error[E0282]: type annotations needed for `Expr<'_, _>`
   --> $DIR/issue-23046.rs:17:15
    |
 LL |     let ex = |x| {
diff --git a/tests/ui/issues/issue-50582.stderr b/tests/ui/issues/issue-50582.stderr
index 1967b51128f..b765d2f087d 100644
--- a/tests/ui/issues/issue-50582.stderr
+++ b/tests/ui/issues/issue-50582.stderr
@@ -16,15 +16,15 @@ LL |     Vec::<[(); 1 + for x in 0..1 {}]>::new();
    |
    = help: the trait `Add<()>` is not implemented for `{integer}`
    = help: the following other types implement trait `Add<Rhs>`:
+             <&'a f128 as Add<f128>>
+             <&'a f16 as Add<f16>>
              <&'a f32 as Add<f32>>
              <&'a f64 as Add<f64>>
              <&'a i128 as Add<i128>>
              <&'a i16 as Add<i16>>
              <&'a i32 as Add<i32>>
              <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+           and 56 others
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/issues/issue-98299.stderr b/tests/ui/issues/issue-98299.stderr
index e99d8e5cc80..becf16d1db9 100644
--- a/tests/ui/issues/issue-98299.stderr
+++ b/tests/ui/issues/issue-98299.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `SmallCString<N>`
+error[E0282]: type annotations needed for `SmallCString<_>`
   --> $DIR/issue-98299.rs:4:36
    |
 LL |     SmallCString::try_from(p).map(|cstr| cstr);
diff --git a/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.rs b/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.rs
new file mode 100644
index 00000000000..59bb65a357b
--- /dev/null
+++ b/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.rs
@@ -0,0 +1,39 @@
+//@ run-pass
+
+#![warn(unused_parens)]
+#![allow(dead_code)]
+
+trait Foo {
+    fn bar();
+    fn tar();
+}
+
+macro_rules! unused_parens {
+    ($ty:ident) => {
+        impl<$ty: Foo> Foo for ($ty,) {
+            fn bar() { <$ty>::bar() }
+            fn tar() {}
+        }
+    };
+
+    ($ty:ident $(, $rest:ident)*) => {
+        impl<$ty: Foo, $($rest: Foo),*> Foo for ($ty, $($rest),*) {
+            fn bar() {
+                <$ty>::bar();
+                <($($rest),*)>::bar() //~WARN unnecessary parentheses around type
+            }
+            fn tar() {
+              let (_t) = 1; //~WARN unnecessary parentheses around pattern
+                            //~| WARN unnecessary parentheses around pattern
+              let (_t1,) = (1,);
+              let (_t2, _t3) = (1, 2);
+            }
+        }
+
+        unused_parens!($($rest),*);
+    }
+}
+
+unused_parens!(T1, T2, T3);
+
+fn main() {}
diff --git a/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.stderr b/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.stderr
new file mode 100644
index 00000000000..b1390debec7
--- /dev/null
+++ b/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.stderr
@@ -0,0 +1,40 @@
+warning: unnecessary parentheses around pattern
+  --> $DIR/unused-parens-in-macro-issue-120642.rs:26:19
+   |
+LL |               let (_t) = 1;
+   |                   ^^^^
+...
+LL | unused_parens!(T1, T2, T3);
+   | -------------------------- in this macro invocation
+   |
+note: the lint level is defined here
+  --> $DIR/unused-parens-in-macro-issue-120642.rs:3:9
+   |
+LL | #![warn(unused_parens)]
+   |         ^^^^^^^^^^^^^
+   = note: this warning originates in the macro `unused_parens` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: unnecessary parentheses around type
+  --> $DIR/unused-parens-in-macro-issue-120642.rs:23:18
+   |
+LL |                 <($($rest),*)>::bar()
+   |                  ^^^^^^^^^^^^
+...
+LL | unused_parens!(T1, T2, T3);
+   | -------------------------- in this macro invocation
+   |
+   = note: this warning originates in the macro `unused_parens` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: unnecessary parentheses around pattern
+  --> $DIR/unused-parens-in-macro-issue-120642.rs:26:19
+   |
+LL |               let (_t) = 1;
+   |                   ^^^^
+...
+LL | unused_parens!(T1, T2, T3);
+   | -------------------------- in this macro invocation
+   |
+   = note: this warning originates in the macro `unused_parens` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
index 0a022dc3984..b2d2d039ff6 100644
--- a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
+++ b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Vec<T>`
+error[E0282]: type annotations needed for `Vec<_>`
   --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:9
    |
 LL |     let mut x = Vec::new();
diff --git a/tests/ui/mismatched_types/binops.stderr b/tests/ui/mismatched_types/binops.stderr
index f8047c8e2d4..099c580a056 100644
--- a/tests/ui/mismatched_types/binops.stderr
+++ b/tests/ui/mismatched_types/binops.stderr
@@ -6,15 +6,15 @@ LL |     1 + Some(1);
    |
    = help: the trait `Add<Option<{integer}>>` is not implemented for `{integer}`
    = help: the following other types implement trait `Add<Rhs>`:
+             <&'a f128 as Add<f128>>
+             <&'a f16 as Add<f16>>
              <&'a f32 as Add<f32>>
              <&'a f64 as Add<f64>>
              <&'a i128 as Add<i128>>
              <&'a i16 as Add<i16>>
              <&'a i32 as Add<i32>>
              <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+           and 56 others
 
 error[E0277]: cannot subtract `Option<{integer}>` from `usize`
   --> $DIR/binops.rs:3:16
@@ -37,15 +37,15 @@ LL |     3 * ();
    |
    = help: the trait `Mul<()>` is not implemented for `{integer}`
    = help: the following other types implement trait `Mul<Rhs>`:
+             <&'a f128 as Mul<f128>>
+             <&'a f16 as Mul<f16>>
              <&'a f32 as Mul<f32>>
              <&'a f64 as Mul<f64>>
              <&'a i128 as Mul<i128>>
              <&'a i16 as Mul<i16>>
              <&'a i32 as Mul<i32>>
              <&'a i64 as Mul<i64>>
-             <&'a i8 as Mul<i8>>
-             <&'a isize as Mul<isize>>
-           and 49 others
+           and 57 others
 
 error[E0277]: cannot divide `{integer}` by `&str`
   --> $DIR/binops.rs:5:7
@@ -55,15 +55,15 @@ LL |     4 / "";
    |
    = help: the trait `Div<&str>` is not implemented for `{integer}`
    = help: the following other types implement trait `Div<Rhs>`:
+             <&'a f128 as Div<f128>>
+             <&'a f16 as Div<f16>>
              <&'a f32 as Div<f32>>
              <&'a f64 as Div<f64>>
              <&'a i128 as Div<i128>>
              <&'a i16 as Div<i16>>
              <&'a i32 as Div<i32>>
              <&'a i64 as Div<i64>>
-             <&'a i8 as Div<i8>>
-             <&'a isize as Div<isize>>
-           and 54 others
+           and 62 others
 
 error[E0277]: can't compare `{integer}` with `String`
   --> $DIR/binops.rs:6:7
diff --git a/tests/ui/suggestions/return-closures.stderr b/tests/ui/suggestions/return-closures.stderr
index 97c13200ac3..ef1f50b8a6c 100644
--- a/tests/ui/suggestions/return-closures.stderr
+++ b/tests/ui/suggestions/return-closures.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/return-closures.rs:3:5
    |
 LL | fn foo() {
-   |         - help: try adding a return type: `-> impl for<'a> Fn(&'a i32) -> i32`
+   |         - help: try adding a return type: `-> impl FnOnce(&i32) -> i32`
 LL |
 LL |     |x: &i32| 1i32
    |     ^^^^^^^^^^^^^^ expected `()`, found closure
diff --git a/tests/ui/traits/copy-guessing.rs b/tests/ui/traits/copy-guessing.rs
index af25010e3bd..0ffa8249789 100644
--- a/tests/ui/traits/copy-guessing.rs
+++ b/tests/ui/traits/copy-guessing.rs
@@ -18,7 +18,7 @@ fn assert_impls_fn<R,T: Fn()->R>(_: &T){}
 
 fn main() {
     let n = None;
-    //~^ ERROR type annotations needed for `Option<T>`
+    //~^ ERROR type annotations needed for `Option<_>`
     let e = S(&n);
     let f = || {
         // S being copy is critical for this to work
diff --git a/tests/ui/traits/copy-guessing.stderr b/tests/ui/traits/copy-guessing.stderr
index 750140c017c..cae91579ee0 100644
--- a/tests/ui/traits/copy-guessing.stderr
+++ b/tests/ui/traits/copy-guessing.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Option<T>`
+error[E0282]: type annotations needed for `Option<_>`
   --> $DIR/copy-guessing.rs:20:9
    |
 LL |     let n = None;
diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr
index 5be8d2f4b32..0f4b3c3c877 100644
--- a/tests/ui/traits/issue-77982.stderr
+++ b/tests/ui/traits/issue-77982.stderr
@@ -55,7 +55,7 @@ help: try using a fully qualified path to specify the expected types
 LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect();
    |                                                      +++++++++++++++++++++++    ~
 
-error[E0283]: type annotations needed for `Box<T>`
+error[E0283]: type annotations needed for `Box<_>`
   --> $DIR/issue-77982.rs:37:9
    |
 LL |     let _ = ().foo();
@@ -73,7 +73,7 @@ help: consider giving this pattern a type, where the type for type parameter `T`
 LL |     let _: Box<T> = ().foo();
    |          ++++++++
 
-error[E0283]: type annotations needed for `Box<T>`
+error[E0283]: type annotations needed for `Box<_>`
   --> $DIR/issue-77982.rs:41:9
    |
 LL |     let _ = (&()).bar();
diff --git a/tests/ui/type-inference/or_else-multiple-type-params.stderr b/tests/ui/type-inference/or_else-multiple-type-params.stderr
index d1bbe308ed3..3176a2d490e 100644
--- a/tests/ui/type-inference/or_else-multiple-type-params.stderr
+++ b/tests/ui/type-inference/or_else-multiple-type-params.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Result<Child, F>`
+error[E0282]: type annotations needed for `Result<Child, _>`
   --> $DIR/or_else-multiple-type-params.rs:7:18
    |
 LL |         .or_else(|err| {
diff --git a/tests/ui/typeck/return_type_containing_closure.rs b/tests/ui/typeck/return_type_containing_closure.rs
index 8b826daeede..b81cac0a58a 100644
--- a/tests/ui/typeck/return_type_containing_closure.rs
+++ b/tests/ui/typeck/return_type_containing_closure.rs
@@ -1,5 +1,5 @@
 #[allow(unused)]
-fn foo() { //~ HELP a return type might be missing here
+fn foo() { //~ HELP try adding a return type
     vec!['a'].iter().map(|c| c)
     //~^ ERROR mismatched types [E0308]
     //~| NOTE expected `()`, found `Map<Iter<'_, char>, ...>`
diff --git a/tests/ui/typeck/return_type_containing_closure.stderr b/tests/ui/typeck/return_type_containing_closure.stderr
index ea9c74be362..3f14650a82c 100644
--- a/tests/ui/typeck/return_type_containing_closure.stderr
+++ b/tests/ui/typeck/return_type_containing_closure.stderr
@@ -10,10 +10,10 @@ help: consider using a semicolon here
    |
 LL |     vec!['a'].iter().map(|c| c);
    |                                +
-help: a return type might be missing here
+help: try adding a return type
    |
-LL | fn foo() -> _ {
-   |          ++++
+LL | fn foo() -> impl Iterator<Item = &char> {
+   |          ++++++++++++++++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr
index 5a76ef3e875..058dbb1e220 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Option<T>`
+error[E0282]: type annotations needed for `Option<_>`
   --> $DIR/unboxed-closures-failed-recursive-fn-2.rs:8:9
    |
 LL |     let mut closure0 = None;