about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs77
-rw-r--r--tests/ui/suggestions/issue-99597.rs15
-rw-r--r--tests/ui/suggestions/issue-99597.stderr15
3 files changed, 76 insertions, 31 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 486c217707e..550a87e6102 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2633,47 +2633,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 Nothing,
                             }
                             let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
-                            let (sp, mut introducer) = if let Some(span) =
-                                ast_generics.bounds_span_for_suggestions(def_id)
-                            {
-                                (span, Introducer::Plus)
-                            } else if let Some(colon_span) = param.colon_span {
-                                (colon_span.shrink_to_hi(), Introducer::Nothing)
-                            } else {
-                                (param.span.shrink_to_hi(), Introducer::Colon)
-                            };
-                            if matches!(
-                                param.kind,
-                                hir::GenericParamKind::Type { synthetic: true, .. },
-                            ) {
-                                introducer = Introducer::Plus
-                            }
                             let trait_def_ids: FxHashSet<DefId> = ast_generics
                                 .bounds_for_param(def_id)
                                 .flat_map(|bp| bp.bounds.iter())
                                 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
                                 .collect();
-                            if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
-                                err.span_suggestions(
-                                    sp,
-                                    message(format!(
-                                        "restrict type parameter `{}` with",
-                                        param.name.ident(),
-                                    )),
+                            if candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
+                                return;
+                            }
+                            let msg = message(format!(
+                                "restrict type parameter `{}` with",
+                                param.name.ident(),
+                            ));
+                            let bounds_span = ast_generics.bounds_span_for_suggestions(def_id);
+                            if rcvr_ty.is_ref() && param.is_impl_trait() && bounds_span.is_some() {
+                                err.multipart_suggestions(
+                                    msg,
                                     candidates.iter().map(|t| {
-                                        format!(
-                                            "{} {}",
-                                            match introducer {
-                                                Introducer::Plus => " +",
-                                                Introducer::Colon => ":",
-                                                Introducer::Nothing => "",
-                                            },
-                                            self.tcx.def_path_str(t.def_id),
-                                        )
+                                        vec![
+                                            (param.span.shrink_to_lo(), "(".to_string()),
+                                            (
+                                                bounds_span.unwrap(),
+                                                format!(" + {})", self.tcx.def_path_str(t.def_id)),
+                                            ),
+                                        ]
                                     }),
                                     Applicability::MaybeIncorrect,
                                 );
+                                return;
                             }
+
+                            let (sp, introducer) = if let Some(span) = bounds_span {
+                                (span, Introducer::Plus)
+                            } else if let Some(colon_span) = param.colon_span {
+                                (colon_span.shrink_to_hi(), Introducer::Nothing)
+                            } else if param.is_impl_trait() {
+                                (param.span.shrink_to_hi(), Introducer::Plus)
+                            } else {
+                                (param.span.shrink_to_hi(), Introducer::Colon)
+                            };
+
+                            err.span_suggestions(
+                                sp,
+                                msg,
+                                candidates.iter().map(|t| {
+                                    format!(
+                                        "{} {}",
+                                        match introducer {
+                                            Introducer::Plus => " +",
+                                            Introducer::Colon => ":",
+                                            Introducer::Nothing => "",
+                                        },
+                                        self.tcx.def_path_str(t.def_id)
+                                    )
+                                }),
+                                Applicability::MaybeIncorrect,
+                            );
                             return;
                         }
                         Node::Item(hir::Item {
diff --git a/tests/ui/suggestions/issue-99597.rs b/tests/ui/suggestions/issue-99597.rs
new file mode 100644
index 00000000000..8ba9e1fdd62
--- /dev/null
+++ b/tests/ui/suggestions/issue-99597.rs
@@ -0,0 +1,15 @@
+#![allow(dead_code)]
+
+trait T1 { }
+
+trait T2 {
+    fn test(&self) { }
+}
+
+fn go(s: &impl T1) {
+    //~^ SUGGESTION (
+    s.test();
+    //~^ ERROR no method named `test`
+}
+
+fn main() { }
diff --git a/tests/ui/suggestions/issue-99597.stderr b/tests/ui/suggestions/issue-99597.stderr
new file mode 100644
index 00000000000..bdf2a07c143
--- /dev/null
+++ b/tests/ui/suggestions/issue-99597.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `test` found for reference `&impl T1` in the current scope
+  --> $DIR/issue-99597.rs:11:7
+   |
+LL |     s.test();
+   |       ^^^^ method not found in `&impl T1`
+   |
+   = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `test`, perhaps you need to restrict type parameter `impl T1` with it:
+   |
+LL | fn go(s: &(impl T1 + T2)) {
+   |           +        +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.