about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs61
-rw-r--r--tests/ui/impl-trait/cross-return-site-inference.stderr10
3 files changed, 53 insertions, 20 deletions
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 a9029a8cec0..e45108d1713 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
@@ -27,7 +27,7 @@ use std::iter;
 
 pub enum TypeAnnotationNeeded {
     /// ```compile_fail,E0282
-    /// let x = "hello".chars().rev().collect();
+    /// let x;
     /// ```
     E0282,
     /// An implementation cannot be chosen unambiguously because of lack of information.
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 5e77b5904f6..49fcd25673d 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -25,7 +25,7 @@ use rustc_errors::{
     MultiSpan, Style,
 };
 use rustc_hir as hir;
-use rustc_hir::def::Namespace;
+use rustc_hir::def::{DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{GenericParam, Item, Node};
@@ -2453,12 +2453,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         && let [
                             ..,
                             trait_path_segment @ hir::PathSegment {
-                                res: rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id),
+                                res: Res::Def(DefKind::Trait, trait_id),
                                 ..
                             },
                             hir::PathSegment {
                                 ident: assoc_item_name,
-                                res: rustc_hir::def::Res::Def(_, item_id),
+                                res: Res::Def(_, item_id),
                                 ..
                             }
                         ] = path.segments
@@ -2469,7 +2469,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         let (verb, noun) = match self.tcx.associated_item(item_id).kind {
                             ty::AssocKind::Const => ("refer to the", "constant"),
                             ty::AssocKind::Fn => ("call", "function"),
-                            ty::AssocKind::Type => ("refer to the", "type"), // this is already covered by E0223, but this single match arm doesn't hurt here
+                            // This is already covered by E0223, but this following single match
+                            // arm doesn't hurt here.
+                            ty::AssocKind::Type => ("refer to the", "type"),
                         };
 
                         // Replace the more general E0283 with a more specific error
@@ -2477,37 +2479,58 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         err = self.tcx.sess.struct_span_err_with_code(
                             span,
                             format!(
-                                "cannot {verb} associated {noun} on trait without specifying the corresponding `impl` type",
+                                "cannot {verb} associated {noun} on trait without specifying the \
+                                 corresponding `impl` type",
                             ),
                             rustc_errors::error_code!(E0790),
                         );
 
                         if let Some(local_def_id) = data.trait_ref.def_id.as_local()
-                            && let Some(hir::Node::Item(hir::Item { ident: trait_name, kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs), .. })) = self.tcx.hir().find_by_def_id(local_def_id)
-                            && let Some(method_ref) = trait_item_refs.iter().find(|item_ref| item_ref.ident == *assoc_item_name) {
-                            err.span_label(method_ref.span, format!("`{trait_name}::{assoc_item_name}` defined here"));
+                            && let Some(hir::Node::Item(hir::Item {
+                                ident: trait_name,
+                                kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs),
+                                ..
+                            })) = self.tcx.hir().find_by_def_id(local_def_id)
+                            && let Some(method_ref) = trait_item_refs
+                                .iter()
+                                .find(|item_ref| item_ref.ident == *assoc_item_name)
+                        {
+                            err.span_label(
+                                method_ref.span,
+                                format!("`{trait_name}::{assoc_item_name}` defined here"),
+                            );
                         }
 
                         err.span_label(span, format!("cannot {verb} associated {noun} of trait"));
 
                         let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
 
-                        if trait_impls.blanket_impls().is_empty()
-                            && let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next()
+                        if let Some(impl_def_id) =
+                            trait_impls.non_blanket_impls().values().flatten().next()
                         {
-                            let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count();
+                            let non_blanket_impl_count =
+                                trait_impls.non_blanket_impls().values().flatten().count();
                             // If there is only one implementation of the trait, suggest using it.
                             // Otherwise, use a placeholder comment for the implementation.
-                            let (message, impl_suggestion) = if non_blanket_impl_count == 1 {(
-                                "use the fully-qualified path to the only available implementation",
-                                format!("<{} as ", self.tcx.type_of(impl_def_id).instantiate_identity())
-                            )} else {
-                                ("use a fully-qualified path to a specific available implementation",
-                                                                "</* self type */ as ".to_string()
-                            )};
+                            let (message, self_type) = if non_blanket_impl_count == 1 {
+                                (
+                                    "use the fully-qualified path to the only available \
+                                     implementation",
+                                    format!(
+                                        "{}",
+                                        self.tcx.type_of(impl_def_id).instantiate_identity()
+                                    ),
+                                )
+                            } else {
+                                (
+                                    "use a fully-qualified path to a specific available \
+                                     implementation",
+                                    "/* self type */".to_string(),
+                                )
+                            };
                             let mut suggestions = vec![(
                                 path.span.shrink_to_lo(),
-                                impl_suggestion
+                                format!("<{self_type} as "),
                             )];
                             if let Some(generic_arg) = trait_path_segment.args {
                                 let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);
diff --git a/tests/ui/impl-trait/cross-return-site-inference.stderr b/tests/ui/impl-trait/cross-return-site-inference.stderr
index a86e00fa04a..8ee3e9abf9c 100644
--- a/tests/ui/impl-trait/cross-return-site-inference.stderr
+++ b/tests/ui/impl-trait/cross-return-site-inference.stderr
@@ -14,12 +14,22 @@ error[E0790]: cannot call associated function on trait without specifying the co
    |
 LL |     return Err(From::from("foo"));
    |                ^^^^^^^^^^ cannot call associated function of trait
+   |
+help: use a fully-qualified path to a specific available implementation
+   |
+LL |     return Err(</* self type */ as From>::from("foo"));
+   |                +++++++++++++++++++     +
 
 error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
   --> $DIR/cross-return-site-inference.rs:44:9
    |
 LL |     Err(From::from("foo"))
    |         ^^^^^^^^^^ cannot call associated function of trait
+   |
+help: use a fully-qualified path to a specific available implementation
+   |
+LL |     Err(</* self type */ as From>::from("foo"))
+   |         +++++++++++++++++++     +
 
 error: aborting due to 3 previous errors