about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_errors/src/emitter.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs41
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs277
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs8
-rw-r--r--compiler/rustc_middle/src/query/erase.rs22
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs26
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_session/src/config.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs29
-rw-r--r--src/librustdoc/clean/inline.rs2
-rw-r--r--src/librustdoc/clean/types.rs1
-rw-r--r--src/librustdoc/clean/utils.rs2
-rw-r--r--src/librustdoc/html/render/write_shared.rs15
-rw-r--r--src/librustdoc/passes/lint/redundant_explicit_links.rs2
-rw-r--r--tests/ui/consts/const-blocks/fn-call-in-non-const.stderr6
-rw-r--r--tests/ui/consts/const-blocks/trait-error.stderr6
-rw-r--r--tests/ui/consts/const-fn-in-vec.rs8
-rw-r--r--tests/ui/consts/const-fn-in-vec.stderr44
-rw-r--r--tests/ui/methods/disambiguate-multiple-blanket-impl.stderr12
-rw-r--r--tests/ui/methods/disambiguate-multiple-impl.stderr8
-rw-r--r--tests/ui/methods/disambiguate-multiple-trait-2.stderr28
-rw-r--r--tests/ui/methods/disambiguate-multiple-trait.stderr12
-rw-r--r--tests/ui/methods/method-ambig-two-traits-from-bounds.stderr8
-rw-r--r--tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr4
-rw-r--r--tests/ui/span/issue-37767.stderr8
28 files changed, 334 insertions, 252 deletions
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 6d95fbcfad0..68dba860291 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -2362,11 +2362,7 @@ impl FileWithAnnotatedLines {
 
                 let label = label.as_ref().map(|m| {
                     normalize_whitespace(
-                        &emitter
-                            .translate_message(m, &args)
-                            .map_err(Report::new)
-                            .unwrap()
-                            .to_string(),
+                        &emitter.translate_message(m, &args).map_err(Report::new).unwrap(),
                     )
                 });
 
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index bb21b027cc9..9f439a2b32a 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -13,7 +13,7 @@ use crate::errors::{
     YieldExprOutsideOfCoroutine,
 };
 use crate::fatally_break_rust;
-use crate::method::{MethodCallComponents, SelfSource};
+use crate::method::SelfSource;
 use crate::type_error_struct;
 use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
 use crate::{
@@ -512,7 +512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let (res, opt_ty, segs) =
-            self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span);
+            self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span, Some(args));
         let ty = match res {
             Res::Err => {
                 self.suggest_assoc_method_call(segs);
@@ -1332,7 +1332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         segment.ident,
                         SelfSource::MethodCall(rcvr),
                         error,
-                        Some(MethodCallComponents { receiver: rcvr, args, full_expr: expr }),
+                        Some(args),
                         expected,
                         false,
                     ) {
@@ -1551,21 +1551,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             _ => {}
         }
-        // If someone calls a const fn, they can extract that call out into a separate constant (or a const
-        // block in the future), so we check that to tell them that in the diagnostic. Does not affect typeck.
-        let is_const_fn = match element.kind {
+        // If someone calls a const fn or constructs a const value, they can extract that
+        // out into a separate constant (or a const block in the future), so we check that
+        // to tell them that in the diagnostic. Does not affect typeck.
+        let is_constable = match element.kind {
             hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
-                ty::FnDef(def_id, _) => tcx.is_const_fn(def_id),
-                _ => false,
+                ty::FnDef(def_id, _) if tcx.is_const_fn(def_id) => traits::IsConstable::Fn,
+                _ => traits::IsConstable::No,
             },
-            _ => false,
+            hir::ExprKind::Path(qpath) => {
+                match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {
+                    Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,
+                    _ => traits::IsConstable::No,
+                }
+            }
+            _ => traits::IsConstable::No,
         };
 
         // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
         // don't copy that one element, we move it. Only check for Copy if the length is larger.
         if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
             let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
-            let code = traits::ObligationCauseCode::RepeatElementCopy { is_const_fn };
+            let code = traits::ObligationCauseCode::RepeatElementCopy {
+                is_constable,
+                elt_type: element_ty,
+                elt_span: element.span,
+                elt_stmt_span: self
+                    .tcx
+                    .hir()
+                    .parent_iter(element.hir_id)
+                    .find_map(|(_, node)| match node {
+                        hir::Node::Item(it) => Some(it.span),
+                        hir::Node::Stmt(stmt) => Some(stmt.span),
+                        _ => None,
+                    })
+                    .expect("array repeat expressions must be inside an item or statement"),
+            };
             self.require_type_meets(element_ty, element.span, code, lang_item);
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index b5a07f0d3e9..750ed2c3491 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -797,6 +797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         qpath: &'tcx QPath<'tcx>,
         hir_id: hir::HirId,
         span: Span,
+        args: Option<&'tcx [hir::Expr<'tcx>]>,
     ) -> (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
         debug!(
             "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
@@ -898,7 +899,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         item_name,
                         SelfSource::QPath(qself),
                         error,
-                        None,
+                        args,
                         Expectation::NoExpectation,
                         trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021
                     ) {
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 86a0e95de1d..d69d2529b18 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -7,7 +7,7 @@ mod prelude2021;
 pub mod probe;
 mod suggest;
 
-pub use self::suggest::{MethodCallComponents, SelfSource};
+pub use self::suggest::SelfSource;
 pub use self::MethodError::*;
 
 use crate::errors::OpMethodGenericParams;
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 87dfcf09cdd..b1a2df8ace4 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -34,7 +34,7 @@ use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::def_id::DefIdSet;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Symbol;
-use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
+use rustc_span::{edit_distance, ExpnKind, FileName, MacroKind, Span};
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
@@ -50,15 +50,6 @@ use rustc_hir::intravisit::Visitor;
 use std::cmp::{self, Ordering};
 use std::iter;
 
-/// After identifying that `full_expr` is a method call, we use this type to keep the expression's
-/// components readily available to us to point at the right place in diagnostics.
-#[derive(Debug, Clone, Copy)]
-pub struct MethodCallComponents<'tcx> {
-    pub receiver: &'tcx hir::Expr<'tcx>,
-    pub args: &'tcx [hir::Expr<'tcx>],
-    pub full_expr: &'tcx hir::Expr<'tcx>,
-}
-
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
         let tcx = self.tcx;
@@ -124,7 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         item_name: Ident,
         source: SelfSource<'tcx>,
         error: MethodError<'tcx>,
-        args: Option<MethodCallComponents<'tcx>>,
+        args: Option<&'tcx [hir::Expr<'tcx>]>,
         expected: Expectation<'tcx>,
         trait_missing_method: bool,
     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
@@ -167,6 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.note_candidates_on_method_error(
                     rcvr_ty,
                     item_name,
+                    source,
                     args,
                     span,
                     &mut err,
@@ -266,23 +258,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn suggest_missing_writer(
         &self,
         rcvr_ty: Ty<'tcx>,
-        args: MethodCallComponents<'tcx>,
+        rcvr_expr: &hir::Expr<'tcx>,
     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
         let (ty_str, _ty_file) = self.tcx.short_ty_string(rcvr_ty);
         let mut err = struct_span_err!(
             self.tcx.sess,
-            args.receiver.span,
+            rcvr_expr.span,
             E0599,
             "cannot write into `{}`",
             ty_str
         );
         err.span_note(
-            args.receiver.span,
+            rcvr_expr.span,
             "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
         );
-        if let ExprKind::Lit(_) = args.receiver.kind {
+        if let ExprKind::Lit(_) = rcvr_expr.kind {
             err.span_help(
-                args.receiver.span.shrink_to_lo(),
+                rcvr_expr.span.shrink_to_lo(),
                 "a writer is needed before this format string",
             );
         };
@@ -296,7 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
         source: SelfSource<'tcx>,
-        args: Option<MethodCallComponents<'tcx>>,
+        args: Option<&'tcx [hir::Expr<'tcx>]>,
         sugg_span: Span,
         no_match_data: &mut NoMatchData<'tcx>,
         expected: Expectation<'tcx>,
@@ -377,23 +369,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             tcx.is_diagnostic_item(sym::write_macro, def_id)
                 || tcx.is_diagnostic_item(sym::writeln_macro, def_id)
         }) && item_name.name == Symbol::intern("write_fmt");
-        let mut err = if is_write && let Some(args) = args {
-            self.suggest_missing_writer(rcvr_ty, args)
-        } else {
-            tcx.sess.create_err(NoAssociatedItem {
-                span,
-                item_kind,
-                item_name,
-                ty_prefix: if trait_missing_method {
-                    // FIXME(mu001999) E0599 maybe not suitable here because it is for types
-                    Cow::from("trait")
-                } else {
-                    rcvr_ty.prefix_string(self.tcx)
-                },
-                ty_str: ty_str_reported,
-                trait_missing_method,
-            })
-        };
+        let mut err =
+            if is_write && let SelfSource::MethodCall(rcvr_expr) = source
+            {
+                self.suggest_missing_writer(rcvr_ty, rcvr_expr)
+            } else {
+                tcx.sess.create_err(NoAssociatedItem {
+                    span,
+                    item_kind,
+                    item_name,
+                    ty_prefix: if trait_missing_method {
+                        // FIXME(mu001999) E0599 maybe not suitable here because it is for types
+                        Cow::from("trait")
+                    } else {
+                        rcvr_ty.prefix_string(self.tcx)
+                    },
+                    ty_str: ty_str_reported,
+                    trait_missing_method,
+                })
+            };
         if tcx.sess.source_map().is_multiline(sugg_span) {
             err.span_label(sugg_span.with_hi(span.lo()), "");
         }
@@ -409,7 +403,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.downgrade_to_delayed_bug();
         }
 
-        self.find_builder_fn(&mut err, rcvr_ty, source);
+        if matches!(source, SelfSource::QPath(_)) && args.is_some() {
+            self.find_builder_fn(&mut err, rcvr_ty);
+        }
+
         if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll {
             err.help(format!(
                 "method `poll` found on `Pin<&mut {ty_str}>`, \
@@ -523,6 +520,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.note_candidates_on_method_error(
                 rcvr_ty,
                 item_name,
+                source,
                 args,
                 span,
                 &mut err,
@@ -533,6 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.note_candidates_on_method_error(
                 rcvr_ty,
                 item_name,
+                source,
                 args,
                 span,
                 &mut err,
@@ -976,7 +975,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 unsatisfied_bounds = true;
             }
         } else if let ty::Adt(def, targs) = rcvr_ty.kind()
-            && let Some(args) = args
+            && let SelfSource::MethodCall(rcvr_expr) = source
         {
             // This is useful for methods on arbitrary self types that might have a simple
             // mutability difference, like calling a method on `Pin<&mut Self>` that is on
@@ -999,8 +998,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         rcvr_ty,
                         &item_segment,
                         span,
-                        args.full_expr,
-                        args.receiver,
+                        tcx.hir().get_parent(rcvr_expr.hir_id).expect_expr(),
+                        rcvr_expr,
                     ) {
                         err.span_note(
                             tcx.def_span(method.def_id),
@@ -1169,7 +1168,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 span,
                 rcvr_ty,
                 item_name,
-                args.map(|MethodCallComponents { args, .. }| args.len() + 1),
+                args.map(|args| args.len() + 1),
                 source,
                 no_match_data.out_of_scope_traits.clone(),
                 &unsatisfied_predicates,
@@ -1250,7 +1249,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
-        args: Option<MethodCallComponents<'tcx>>,
+        self_source: SelfSource<'tcx>,
+        args: Option<&'tcx [hir::Expr<'tcx>]>,
         span: Span,
         err: &mut Diagnostic,
         sources: &mut Vec<CandidateSource>,
@@ -1320,38 +1320,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     if let Some(sugg_span) = sugg_span
                         && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did)
-                    {
-                        let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id);
-
-                        let ty = match item.kind {
-                            ty::AssocKind::Const | ty::AssocKind::Type => impl_ty,
-                            ty::AssocKind::Fn => self
-                                .tcx
-                                .fn_sig(item.def_id)
-                                .instantiate_identity()
-                                .inputs()
-                                .skip_binder()
-                                .get(0)
-                                .filter(|ty| ty.is_ref() && !rcvr_ty.is_ref())
-                                .copied()
-                                .unwrap_or(rcvr_ty),
-                        };
-                        if let Some(sugg) = print_disambiguation_help(
-                            item_name,
-                            args,
+                        && let Some(sugg) = print_disambiguation_help(
+                            self.tcx,
                             err,
-                            path,
-                            ty,
-                            Some(impl_ty),
-                            item.kind,
-                            self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id),
-                            sugg_span,
+                            self_source,
+                            args,
+                            trait_ref.instantiate(
+                                self.tcx,
+                                self.fresh_args_for_item(sugg_span, impl_did)
+                            ).with_self_ty(self.tcx, rcvr_ty),
                             idx,
-                            self.tcx.sess.source_map(),
-                            item.fn_has_self_parameter,
-                        ) {
-                            suggs.push(sugg);
-                        }
+                            sugg_span,
+                            item,
+                        )
+                    {
+                        suggs.push(sugg);
                     }
                 }
                 CandidateSource::Trait(trait_did) => {
@@ -1373,24 +1356,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         err.span_note(item_span, msg);
                         None
                     };
-                    if let Some(sugg_span) = sugg_span {
-                        let path = self.tcx.def_path_str(trait_did);
-                        if let Some(sugg) = print_disambiguation_help(
-                            item_name,
-                            args,
+                    if let Some(sugg_span) = sugg_span
+                        && let Some(sugg) = print_disambiguation_help(
+                            self.tcx,
                             err,
-                            path,
-                            rcvr_ty,
-                            None,
-                            item.kind,
-                            self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id),
-                            sugg_span,
+                            self_source,
+                            args,
+                            ty::TraitRef::new(
+                                self.tcx,
+                                trait_did,
+                                self.fresh_args_for_item(sugg_span, trait_did)
+                            ).with_self_ty(self.tcx, rcvr_ty),
                             idx,
-                            self.tcx.sess.source_map(),
-                            item.fn_has_self_parameter,
-                        ) {
-                            suggs.push(sugg);
-                        }
+                            sugg_span,
+                            item,
+                        )
+                    {
+                        suggs.push(sugg);
                     }
                 }
             }
@@ -1410,18 +1392,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// Look at all the associated functions without receivers in the type's inherent impls
     /// to look for builders that return `Self`, `Option<Self>` or `Result<Self, _>`.
-    fn find_builder_fn(&self, err: &mut Diagnostic, rcvr_ty: Ty<'tcx>, source: SelfSource<'tcx>) {
+    fn find_builder_fn(&self, err: &mut Diagnostic, rcvr_ty: Ty<'tcx>) {
         let ty::Adt(adt_def, _) = rcvr_ty.kind() else {
             return;
         };
-        let SelfSource::QPath(ty) = source else {
-            return;
-        };
-        let hir = self.tcx.hir();
-        if let Some(Node::Pat(_)) = hir.find(hir.parent_id(ty.hir_id)) {
-            // Do not suggest a fn call when a pattern is expected.
-            return;
-        }
         let mut items = self
             .tcx
             .inherent_impls(adt_def.did())
@@ -1504,7 +1478,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rcvr_ty: Ty<'tcx>,
         source: SelfSource<'tcx>,
         item_name: Ident,
-        args: Option<MethodCallComponents<'tcx>>,
+        args: Option<&'tcx [hir::Expr<'tcx>]>,
         sugg_span: Span,
     ) {
         let mut has_unsuggestable_args = false;
@@ -1578,38 +1552,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 None
             };
             let mut applicability = Applicability::MachineApplicable;
-            let args = if let Some(MethodCallComponents { receiver, args, .. }) = args {
-                // The first arg is the same kind as the receiver
-                let explicit_args = if first_arg.is_some() {
-                    std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
+            let args = if let SelfSource::MethodCall(receiver) = source
+                    && let Some(args) = args
+                {
+                    // The first arg is the same kind as the receiver
+                    let explicit_args = if first_arg.is_some() {
+                        std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
+                    } else {
+                        // There is no `Self` kind to infer the arguments from
+                        if has_unsuggestable_args {
+                            applicability = Applicability::HasPlaceholders;
+                        }
+                        args.iter().collect()
+                    };
+                    format!(
+                        "({}{})",
+                        first_arg.unwrap_or(""),
+                        explicit_args
+                            .iter()
+                            .map(|arg| self
+                                .tcx
+                                .sess
+                                .source_map()
+                                .span_to_snippet(arg.span)
+                                .unwrap_or_else(|_| {
+                                    applicability = Applicability::HasPlaceholders;
+                                    "_".to_owned()
+                                }))
+                            .collect::<Vec<_>>()
+                            .join(", "),
+                    )
                 } else {
-                    // There is no `Self` kind to infer the arguments from
-                    if has_unsuggestable_args {
-                        applicability = Applicability::HasPlaceholders;
-                    }
-                    args.iter().collect()
+                    applicability = Applicability::HasPlaceholders;
+                    "(...)".to_owned()
                 };
-                format!(
-                    "({}{})",
-                    first_arg.unwrap_or(""),
-                    explicit_args
-                        .iter()
-                        .map(|arg| self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_to_snippet(arg.span)
-                            .unwrap_or_else(|_| {
-                                applicability = Applicability::HasPlaceholders;
-                                "_".to_owned()
-                            }))
-                        .collect::<Vec<_>>()
-                        .join(", "),
-                )
-            } else {
-                applicability = Applicability::HasPlaceholders;
-                "(...)".to_owned()
-            };
             err.span_suggestion(
                 sugg_span,
                 "use associated function syntax instead",
@@ -3267,56 +3243,59 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
 }
 
 fn print_disambiguation_help<'tcx>(
-    item_name: Ident,
-    args: Option<MethodCallComponents<'tcx>>,
+    tcx: TyCtxt<'tcx>,
     err: &mut Diagnostic,
-    trait_name: String,
-    rcvr_ty: Ty<'_>,
-    impl_self_ty: Option<Ty<'_>>,
-    kind: ty::AssocKind,
-    def_kind_descr: &'static str,
+    source: SelfSource<'tcx>,
+    args: Option<&'tcx [hir::Expr<'tcx>]>,
+    trait_ref: ty::TraitRef<'tcx>,
+    candidate_idx: Option<usize>,
     span: Span,
-    candidate: Option<usize>,
-    source_map: &source_map::SourceMap,
-    fn_has_self_parameter: bool,
+    item: ty::AssocItem,
 ) -> Option<String> {
+    let trait_ref = if item.fn_has_self_parameter {
+        trait_ref.print_only_trait_name().to_string()
+    } else {
+        format!("<{} as {}>", trait_ref.args[0], trait_ref.print_only_trait_name())
+    };
     Some(
-        if let (ty::AssocKind::Fn, Some(MethodCallComponents { receiver, args, .. })) = (kind, args)
+        if matches!(item.kind, ty::AssocKind::Fn)
+            && let SelfSource::MethodCall(receiver) = source
+            && let Some(args) = args
         {
+            let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id);
+            let item_name = item.ident(tcx);
+            let rcvr_ref = tcx.fn_sig(item.def_id).skip_binder().skip_binder().inputs()[0]
+                .ref_mutability()
+                .map_or("", |mutbl| mutbl.ref_prefix_str());
             let args = format!(
                 "({}{})",
-                rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
+                rcvr_ref,
                 std::iter::once(receiver)
                     .chain(args.iter())
-                    .map(|arg| source_map
+                    .map(|arg| tcx
+                        .sess
+                        .source_map()
                         .span_to_snippet(arg.span)
                         .unwrap_or_else(|_| { "_".to_owned() }))
                     .collect::<Vec<_>>()
                     .join(", "),
             );
-            let trait_name = if !fn_has_self_parameter && let Some(impl_self_ty) = impl_self_ty {
-            format!("<{impl_self_ty} as {trait_name}>")
-        } else {
-            trait_name
-        };
             err.span_suggestion_verbose(
                 span,
                 format!(
                     "disambiguate the {def_kind_descr} for {}",
-                    if let Some(candidate) = candidate {
+                    if let Some(candidate) = candidate_idx {
                         format!("candidate #{candidate}")
                     } else {
                         "the candidate".to_string()
                     },
                 ),
-                format!("{trait_name}::{item_name}{args}"),
+                format!("{trait_ref}::{item_name}{args}"),
                 Applicability::HasPlaceholders,
             );
             return None;
-        } else if let Some(impl_self_ty) = impl_self_ty {
-            format!("<{impl_self_ty} as {trait_name}>::")
         } else {
-            format!("{trait_name}::")
+            format!("{trait_ref}::")
         },
     )
 }
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 50684482c0d..b30f9b82fbb 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -166,9 +166,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) {
         let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info;
         let path_res = match &pat.kind {
-            PatKind::Path(qpath) => {
-                Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span))
-            }
+            PatKind::Path(qpath) => Some(
+                self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None),
+            ),
             _ => None,
         };
         let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
@@ -1060,7 +1060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Resolve the path and check the definition for errors.
         let (res, opt_ty, segments) =
-            self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
+            self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None);
         if res == Res::Err {
             let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
             self.set_tainted_by_errors(e);
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index e20e9d9312c..cdde6a596a8 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -2,7 +2,8 @@ use crate::mir;
 use crate::query::CyclePlaceholder;
 use crate::traits;
 use crate::ty::{self, Ty};
-use std::mem::{size_of, transmute_copy, MaybeUninit};
+use std::intrinsics::transmute_unchecked;
+use std::mem::{size_of, MaybeUninit};
 
 #[derive(Copy, Clone)]
 pub struct Erased<T: Copy> {
@@ -29,8 +30,15 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> {
     };
 
     Erased::<<T as EraseType>::Result> {
+        // `transmute_unchecked` is needed here because it does not have `transmute`'s size check
+        // (and thus allows to transmute between `T` and `MaybeUninit<T::Result>`) (we do the size
+        // check ourselves in the `const` block above).
+        //
+        // `transmute_copy` is also commonly used for this (and it would work here since
+        // `EraseType: Copy`), but `transmute_unchecked` better explains the intent.
+        //
         // SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes.
-        data: unsafe { transmute_copy(&src) },
+        data: unsafe { transmute_unchecked::<T, MaybeUninit<T::Result>>(src) },
     }
 }
 
@@ -38,22 +46,24 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> {
 #[inline(always)]
 pub fn restore<T: EraseType>(value: Erase<T>) -> T {
     let value: Erased<<T as EraseType>::Result> = value;
+    // See comment in `erase` for why we use `transmute_unchecked`.
+    //
     // SAFETY: Due to the use of impl Trait in `Erase` the only way to safely create an instance
     // of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of
     // the right size.
-    unsafe { transmute_copy(&value.data) }
+    unsafe { transmute_unchecked::<MaybeUninit<T::Result>, T>(value.data) }
 }
 
 impl<T> EraseType for &'_ T {
-    type Result = [u8; size_of::<*const ()>()];
+    type Result = [u8; size_of::<&'static ()>()];
 }
 
 impl<T> EraseType for &'_ [T] {
-    type Result = [u8; size_of::<*const [()]>()];
+    type Result = [u8; size_of::<&'static [()]>()];
 }
 
 impl<T> EraseType for &'_ ty::List<T> {
-    type Result = [u8; size_of::<*const ()>()];
+    type Result = [u8; size_of::<&'static ty::List<()>>()];
 }
 
 impl<I: rustc_index::Idx, T> EraseType for &'_ rustc_index::IndexSlice<I, T> {
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 9e2ff3820af..6cd75e08727 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -305,9 +305,14 @@ pub enum ObligationCauseCode<'tcx> {
     SizedCoroutineInterior(LocalDefId),
     /// `[expr; N]` requires `type_of(expr): Copy`.
     RepeatElementCopy {
-        /// If element is a `const fn` we display a help message suggesting to move the
-        /// function call to a new `const` item while saying that `T` doesn't implement `Copy`.
-        is_const_fn: bool,
+        /// If element is a `const fn` or const ctor we display a help message suggesting
+        /// to move it to a new `const` item while saying that `T` doesn't implement `Copy`.
+        is_constable: IsConstable,
+        elt_type: Ty<'tcx>,
+        elt_span: Span,
+        /// Span of the statement/item in which the repeat expression occurs. We can use this to
+        /// place a `const` declaration before it
+        elt_stmt_span: Span,
     },
 
     /// Types of fields (other than the last, except for packed structs) in a struct must be sized.
@@ -455,6 +460,21 @@ pub enum ObligationCauseCode<'tcx> {
     TypeAlias(InternedObligationCauseCode<'tcx>, Span, DefId),
 }
 
+/// Whether a value can be extracted into a const.
+/// Used for diagnostics around array repeat expressions.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub enum IsConstable {
+    No,
+    /// Call to a const fn
+    Fn,
+    /// Use of a const ctor
+    Ctor,
+}
+
+crate::TrivialTypeTraversalAndLiftImpls! {
+    IsConstable,
+}
+
 /// The 'location' at which we try to perform HIR-based wf checking.
 /// This information is used to obtain an `hir::Ty`, which
 /// we can walk in order to obtain precise spans for any
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 77a50fa9276..0094825fc70 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -274,7 +274,7 @@ pub fn suggest_constraining_type_params<'a>(
                 span,
                 if span_to_replace.is_some() {
                     constraint.clone()
-                } else if constraint.starts_with("<") {
+                } else if constraint.starts_with('<') {
                     constraint.to_string()
                 } else if bound_list_non_empty {
                     format!(" + {constraint}")
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index edcc22d56c6..93db6cfc463 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1545,7 +1545,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let (span, sugg, post) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
             && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
             && let Some(span) = suggestion.span
-            && let Some(candidate) = suggestion.candidate.as_str().strip_prefix("_")
+            && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_')
             && snippet == candidate
         {
             // When the suggested binding change would be from `x` to `_x`, suggest changing the
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index c94e0d0ed39..930fb693eb6 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2477,7 +2477,7 @@ pub fn parse_externs(
             let mut error = handler.early_struct_error(format!(
                 "crate name `{name}` passed to `--extern` is not a valid ASCII identifier"
             ));
-            let adjusted_name = name.replace("-", "_");
+            let adjusted_name = name.replace('-', "_");
             if crate::utils::is_ascii_ident(&adjusted_name) {
                 error.help(format!(
                     "consider replacing the dashes with underscores: `{adjusted_name}`"
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 78ceddcd263..6b09bc89873 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -28,6 +28,7 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk, LateBoundRegionConversionTime};
 use rustc_middle::hir::map;
+use rustc_middle::traits::IsConstable;
 use rustc_middle::ty::error::TypeError::{self, Sorts};
 use rustc_middle::ty::{
     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, GenericArgs,
@@ -2768,20 +2769,30 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     ));
                 }
             }
-            ObligationCauseCode::RepeatElementCopy { is_const_fn } => {
+            ObligationCauseCode::RepeatElementCopy { is_constable, elt_type, elt_span, elt_stmt_span } => {
                 err.note(
                     "the `Copy` trait is required because this value will be copied for each element of the array",
                 );
-
-                if is_const_fn {
-                    err.help(
-                        "consider creating a new `const` item and initializing it with the result \
-                        of the function call to be used in the repeat position, like \
-                        `const VAL: Type = const_fn();` and `let x = [VAL; 42];`",
-                    );
+                let value_kind = match is_constable {
+                    IsConstable::Fn => Some("the result of the function call"),
+                    IsConstable::Ctor => Some("the result of the constructor"),
+                    _ => None
+                };
+                let sm = tcx.sess.source_map();
+                if let Some(value_kind) = value_kind &&
+                    let Ok(snip) = sm.span_to_snippet(elt_span)
+                {
+                    let help_msg = format!(
+                        "consider creating a new `const` item and initializing it with {value_kind} \
+                        to be used in the repeat position");
+                    let indentation = sm.indentation_before(elt_stmt_span).unwrap_or_default();
+                    err.multipart_suggestion(help_msg, vec![
+                        (elt_stmt_span.shrink_to_lo(), format!("const ARRAY_REPEAT_VALUE: {elt_type} = {snip};\n{indentation}")),
+                        (elt_span, "ARRAY_REPEAT_VALUE".to_string())
+                    ], Applicability::MachineApplicable);
                 }
 
-                if self.tcx.sess.is_nightly_build() && is_const_fn {
+                if self.tcx.sess.is_nightly_build() && matches!(is_constable, IsConstable::Fn|IsConstable::Ctor) {
                     err.help(
                         "create an inline `const` block, see RFC #2920 \
                          <https://github.com/rust-lang/rfcs/pull/2920> for more information",
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 013814b1f7d..974ba1e3bd9 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -599,7 +599,7 @@ fn build_module_items(
                 let prim_ty = clean::PrimitiveType::from(p);
                 items.push(clean::Item {
                     name: None,
-                    attrs: Box::new(clean::Attributes::default()),
+                    attrs: Box::default(),
                     // We can use the item's `DefId` directly since the only information ever used
                     // from it is `DefId.krate`.
                     item_id: ItemId::DefId(did),
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index a718cb37d89..88ee4e3a2ab 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1327,6 +1327,7 @@ impl WherePredicate {
 pub(crate) enum GenericParamDefKind {
     Lifetime { outlives: ThinVec<Lifetime> },
     Type { did: DefId, bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
+    // Option<Box<String>> makes this type smaller than `Option<String>` would.
     Const { ty: Box<Type>, default: Option<Box<String>>, is_host_effect: bool },
 }
 
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index dea7bfaf7e2..ca1b782492c 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -588,7 +588,7 @@ pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool {
 /// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
 pub(crate) const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL");
 pub(crate) static DOC_CHANNEL: Lazy<&'static str> =
-    Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit("/").filter(|c| !c.is_empty()).next().unwrap());
+    Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit('/').filter(|c| !c.is_empty()).next().unwrap());
 
 /// Render a sequence of macro arms in a format suitable for displaying to the user
 /// as part of an item declaration.
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 3e58dd96ed9..d2c7c578c08 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -356,15 +356,12 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
 
             let content = format!(
                 "<h1>List of all crates</h1><ul class=\"all-items\">{}</ul>",
-                krates
-                    .iter()
-                    .map(|s| {
-                        format!(
-                            "<li><a href=\"{trailing_slash}index.html\">{s}</a></li>",
-                            trailing_slash = ensure_trailing_slash(s),
-                        )
-                    })
-                    .collect::<String>()
+                krates.iter().format_with("", |k, f| {
+                    f(&format_args!(
+                        "<li><a href=\"{trailing_slash}index.html\">{k}</a></li>",
+                        trailing_slash = ensure_trailing_slash(k),
+                    ))
+                })
             );
             let v = layout::render(&shared.layout, &page, "", content, &shared.style_files);
             shared.fs.write(dst, v)?;
diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs
index 0c15bf5f764..472781e7d22 100644
--- a/src/librustdoc/passes/lint/redundant_explicit_links.rs
+++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs
@@ -87,7 +87,7 @@ fn check_redundant_explicit_link<'md>(
                 let link_data = collect_link_data(&mut offset_iter);
 
                 if let Some(resolvable_link) = link_data.resolvable_link.as_ref() {
-                    if &link_data.display_link.replace("`", "") != resolvable_link {
+                    if &link_data.display_link.replace('`', "") != resolvable_link {
                         // Skips if display link does not match to actual
                         // resolvable link, usually happens if display link
                         // has several segments, e.g.
diff --git a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr
index 174103eeba4..eb8b8ac7534 100644
--- a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr
+++ b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr
@@ -6,13 +6,17 @@ LL |     let _: [Option<Bar>; 2] = [no_copy(); 2];
    |
    = note: required for `Option<Bar>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
-   = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];`
    = help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
 help: consider annotating `Bar` with `#[derive(Copy)]`
    |
 LL + #[derive(Copy)]
 LL | struct Bar;
    |
+help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position
+   |
+LL ~     const ARRAY_REPEAT_VALUE: Option<Bar> = no_copy();
+LL ~     let _: [Option<Bar>; 2] = [ARRAY_REPEAT_VALUE; 2];
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr
index 06fa4b0b1f3..858ffa820e2 100644
--- a/tests/ui/consts/const-blocks/trait-error.stderr
+++ b/tests/ui/consts/const-blocks/trait-error.stderr
@@ -10,9 +10,13 @@ note: required for `Foo<String>` to implement `Copy`
 LL | #[derive(Copy, Clone)]
    |          ^^^^ unsatisfied trait bound introduced in this `derive` macro
    = note: the `Copy` trait is required because this value will be copied for each element of the array
-   = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];`
    = help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position
+   |
+LL ~     const ARRAY_REPEAT_VALUE: Foo<String> = Foo(String::new());
+LL ~     [ARRAY_REPEAT_VALUE; 4];
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/const-fn-in-vec.rs b/tests/ui/consts/const-fn-in-vec.rs
index a40290eca09..0483800efef 100644
--- a/tests/ui/consts/const-fn-in-vec.rs
+++ b/tests/ui/consts/const-fn-in-vec.rs
@@ -1,7 +1,11 @@
+static _MAYBE_STRINGS: [Option<String>; 5] = [None; 5];
+//~^ ERROR the trait bound `String: Copy` is not satisfied
+
 fn main() {
     // should hint to create an inline `const` block
     // or to create a new `const` item
-    let strings: [String; 5] = [String::new(); 5];
+    let _strings: [String; 5] = [String::new(); 5];
+    //~^ ERROR the trait bound `String: Copy` is not satisfied
+    let _maybe_strings: [Option<String>; 5] = [None; 5];
     //~^ ERROR the trait bound `String: Copy` is not satisfied
-    println!("{:?}", strings);
 }
diff --git a/tests/ui/consts/const-fn-in-vec.stderr b/tests/ui/consts/const-fn-in-vec.stderr
index 9eb7524b504..4593034bfae 100644
--- a/tests/ui/consts/const-fn-in-vec.stderr
+++ b/tests/ui/consts/const-fn-in-vec.stderr
@@ -1,13 +1,47 @@
 error[E0277]: the trait bound `String: Copy` is not satisfied
-  --> $DIR/const-fn-in-vec.rs:4:33
+  --> $DIR/const-fn-in-vec.rs:1:47
    |
-LL |     let strings: [String; 5] = [String::new(); 5];
-   |                                 ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+LL | static _MAYBE_STRINGS: [Option<String>; 5] = [None; 5];
+   |                                               ^^^^ the trait `Copy` is not implemented for `String`
    |
+   = note: required for `Option<String>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
-   = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];`
    = help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
+help: consider creating a new `const` item and initializing it with the result of the constructor to be used in the repeat position
+   |
+LL + const ARRAY_REPEAT_VALUE: Option<String> = None;
+LL ~ static _MAYBE_STRINGS: [Option<String>; 5] = [ARRAY_REPEAT_VALUE; 5];
+   |
+
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/const-fn-in-vec.rs:7:34
+   |
+LL |     let _strings: [String; 5] = [String::new(); 5];
+   |                                  ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |
+   = note: the `Copy` trait is required because this value will be copied for each element of the array
+   = help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
+help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position
+   |
+LL ~     const ARRAY_REPEAT_VALUE: String = String::new();
+LL ~     let _strings: [String; 5] = [ARRAY_REPEAT_VALUE; 5];
+   |
+
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/const-fn-in-vec.rs:9:48
+   |
+LL |     let _maybe_strings: [Option<String>; 5] = [None; 5];
+   |                                                ^^^^ the trait `Copy` is not implemented for `String`
+   |
+   = note: required for `Option<String>` to implement `Copy`
+   = note: the `Copy` trait is required because this value will be copied for each element of the array
+   = help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
+help: consider creating a new `const` item and initializing it with the result of the constructor to be used in the repeat position
+   |
+LL ~     const ARRAY_REPEAT_VALUE: Option<String> = None;
+LL ~     let _maybe_strings: [Option<String>; 5] = [ARRAY_REPEAT_VALUE; 5];
+   |
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr
index a9e9c679fdb..ccdd9a95451 100644
--- a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr
+++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr
@@ -29,10 +29,10 @@ LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <T as A>::foo(&s);
-   |     ~~~~~~~~~~
-LL |     <T as B>::foo(&s);
-   |     ~~~~~~~~~~
+LL |     A::foo(&s);
+   |     ~~~
+LL |     B::foo(&s);
+   |     ~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-blanket-impl.rs:33:8
@@ -52,9 +52,9 @@ LL |     const CONST: usize = 2;
    |     ^^^^^^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <T as A>::CONST;
+LL |     <S as A>::CONST;
    |     ~~~~~~~~~~
-LL |     <T as B>::CONST;
+LL |     <S as B>::CONST;
    |     ~~~~~~~~~~
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr
index 901bfc30a3f..4172120770c 100644
--- a/tests/ui/methods/disambiguate-multiple-impl.stderr
+++ b/tests/ui/methods/disambiguate-multiple-impl.stderr
@@ -29,10 +29,10 @@ LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <S as A>::foo(&s);
-   |     ~~~~~~~~~~
-LL |     <S as B>::foo(&s);
-   |     ~~~~~~~~~~
+LL |     A::foo(&s);
+   |     ~~~
+LL |     B::foo(&s);
+   |     ~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-impl.rs:34:16
diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.stderr b/tests/ui/methods/disambiguate-multiple-trait-2.stderr
index 0f9c60ce243..2778f254a56 100644
--- a/tests/ui/methods/disambiguate-multiple-trait-2.stderr
+++ b/tests/ui/methods/disambiguate-multiple-trait-2.stderr
@@ -37,12 +37,12 @@ LL |     fn foo(&self);
    |     ^^^^^^^^^^^^^^
 help: disambiguate the method for candidate #1
    |
-LL |     A::foo(t);
-   |     ~~~~~~~~~
+LL |     A::foo(&t);
+   |     ~~~~~~~~~~
 help: disambiguate the method for candidate #2
    |
-LL |     B::foo(t);
-   |     ~~~~~~~~~
+LL |     B::foo(&t);
+   |     ~~~~~~~~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-trait-2.rs:20:16
@@ -62,10 +62,10 @@ LL |     const CONST: usize;
    |     ^^^^^^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     let _ = A::CONST;
-   |             ~~~
-LL |     let _ = B::CONST;
-   |             ~~~
+LL |     let _ = <T as A>::CONST;
+   |             ~~~~~~~~~~
+LL |     let _ = <T as B>::CONST;
+   |             ~~~~~~~~~~
 
 error[E0223]: ambiguous associated type
   --> $DIR/disambiguate-multiple-trait-2.rs:52:12
@@ -98,10 +98,10 @@ LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <T as A>::foo(&s);
-   |     ~~~~~~~~~~
-LL |     <T as B>::foo(&s);
-   |     ~~~~~~~~~~
+LL |     A::foo(&s);
+   |     ~~~
+LL |     B::foo(&s);
+   |     ~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-trait-2.rs:49:16
@@ -121,9 +121,9 @@ LL |     const CONST: usize = 1;
    |     ^^^^^^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     let _ = <T as A>::CONST;
+LL |     let _ = <S as A>::CONST;
    |             ~~~~~~~~~~
-LL |     let _ = <T as B>::CONST;
+LL |     let _ = <S as B>::CONST;
    |             ~~~~~~~~~~
 
 error: aborting due to 6 previous errors
diff --git a/tests/ui/methods/disambiguate-multiple-trait.stderr b/tests/ui/methods/disambiguate-multiple-trait.stderr
index 9a50d51245b..e00498ca62b 100644
--- a/tests/ui/methods/disambiguate-multiple-trait.stderr
+++ b/tests/ui/methods/disambiguate-multiple-trait.stderr
@@ -29,10 +29,10 @@ LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <T as A>::foo(&s);
-   |     ~~~~~~~~~~
-LL |     <T as B>::foo(&s);
-   |     ~~~~~~~~~~
+LL |     A::foo(&s);
+   |     ~~~
+LL |     B::foo(&s);
+   |     ~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-trait.rs:27:16
@@ -52,9 +52,9 @@ LL |     const CONST: usize = 2;
    |     ^^^^^^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     let _ = <T as A>::CONST;
+LL |     let _ = <S as A>::CONST;
    |             ~~~~~~~~~~
-LL |     let _ = <T as B>::CONST;
+LL |     let _ = <S as B>::CONST;
    |             ~~~~~~~~~~
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr
index 601e6bbb006..9a84768a9f4 100644
--- a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr
+++ b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr
@@ -16,12 +16,12 @@ LL | trait B { fn foo(&self); }
    |           ^^^^^^^^^^^^^^
 help: disambiguate the method for candidate #1
    |
-LL |     A::foo(t);
-   |     ~~~~~~~~~
+LL |     A::foo(&t);
+   |     ~~~~~~~~~~
 help: disambiguate the method for candidate #2
    |
-LL |     B::foo(t);
-   |     ~~~~~~~~~
+LL |     B::foo(&t);
+   |     ~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
index 4e83e4b77f1..755179650bb 100644
--- a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
+++ b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
@@ -54,8 +54,8 @@ LL |     let z = NuisanceFoo::foo(x);
    |             ~~~~~~~~~~~~~~~~~~~
 help: disambiguate the method for candidate #3
    |
-LL |     let z = FinalFoo::foo(x);
-   |             ~~~~~~~~~~~~~~~~
+LL |     let z = FinalFoo::foo(&x);
+   |             ~~~~~~~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:139:24
diff --git a/tests/ui/span/issue-37767.stderr b/tests/ui/span/issue-37767.stderr
index b612fdf16fc..457870821a1 100644
--- a/tests/ui/span/issue-37767.stderr
+++ b/tests/ui/span/issue-37767.stderr
@@ -16,12 +16,12 @@ LL |     fn foo(&mut self) {}
    |     ^^^^^^^^^^^^^^^^^
 help: disambiguate the method for candidate #1
    |
-LL |     A::foo(&a)
-   |     ~~~~~~~~~~
+LL |     A::foo(&mut a)
+   |     ~~~~~~~~~~~~~~
 help: disambiguate the method for candidate #2
    |
-LL |     B::foo(&a)
-   |     ~~~~~~~~~~
+LL |     B::foo(&mut a)
+   |     ~~~~~~~~~~~~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/issue-37767.rs:22:7