about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-10-03 21:52:44 +0200
committerGitHub <noreply@github.com>2024-10-03 21:52:44 +0200
commit0d65f121a12935c4d827143caab7d46790a12204 (patch)
tree8dda80a1c5d4951ef3c82e73c93fcb1ca2bddb77
parent56e35a5dbb37898433a43133dff0398f46d577b8 (diff)
parent486440fc7482adf1c57681ffaa34cf9b5fb157eb (diff)
downloadrust-0d65f121a12935c4d827143caab7d46790a12204.tar.gz
rust-0d65f121a12935c4d827143caab7d46790a12204.zip
Rollup merge of #131024 - compiler-errors:deref-sugg, r=estebank
Don't give method suggestions when method probe fails due to bad implementation of `Deref`

If we have a bad `Deref` impl, we used to bail with `MethodError::NoMatch`, which makes the error reporting code think that there was no applicable method (and thus try to suggest importing something, even if it's in scope).

Suppress this error, which fixes #131003.
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs18
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs34
-rw-r--r--tests/ui/methods/dont-suggest-import-on-deref-err.rs13
-rw-r--r--tests/ui/methods/dont-suggest-import-on-deref-err.stderr12
5 files changed, 54 insertions, 31 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 586b753f454..3e9cb0ac2c8 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -18,8 +18,8 @@ use rustc_middle::ty::{
     self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TypeVisitableExt,
 };
 use rustc_middle::{bug, span_bug};
-use rustc_span::Span;
 use rustc_span::symbol::Ident;
+use rustc_span::{ErrorGuaranteed, Span};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{self, NormalizeExt};
 use tracing::{debug, instrument};
@@ -46,17 +46,17 @@ pub(crate) struct MethodCallee<'tcx> {
 
 #[derive(Debug)]
 pub(crate) enum MethodError<'tcx> {
-    // Did not find an applicable method, but we did find various near-misses that may work.
+    /// Did not find an applicable method, but we did find various near-misses that may work.
     NoMatch(NoMatchData<'tcx>),
 
-    // Multiple methods might apply.
+    /// Multiple methods might apply.
     Ambiguity(Vec<CandidateSource>),
 
-    // Found an applicable method, but it is not visible. The third argument contains a list of
-    // not-in-scope traits which may work.
+    /// Found an applicable method, but it is not visible. The third argument contains a list of
+    /// not-in-scope traits which may work.
     PrivateMatch(DefKind, DefId, Vec<DefId>),
 
-    // Found a `Self: Sized` bound where `Self` is a trait object.
+    /// Found a `Self: Sized` bound where `Self` is a trait object.
     IllegalSizedBound {
         candidates: Vec<DefId>,
         needs_mut: bool,
@@ -64,8 +64,11 @@ pub(crate) enum MethodError<'tcx> {
         self_expr: &'tcx hir::Expr<'tcx>,
     },
 
-    // Found a match, but the return type is wrong
+    /// Found a match, but the return type is wrong
     BadReturnType,
+
+    /// Error has already been emitted, no need to emit another one.
+    ErrorReported(ErrorGuaranteed),
 }
 
 // Contains a list of static methods that may apply, a list of unsatisfied trait predicates which
@@ -120,6 +123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Err(PrivateMatch(..)) => false,
             Err(IllegalSizedBound { .. }) => true,
             Err(BadReturnType) => false,
+            Err(ErrorReported(_)) => false,
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 371380e575d..3bb7070d61d 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -446,13 +446,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     _ => bug!("unexpected bad final type in method autoderef"),
                 };
                 self.demand_eqtype(span, ty, Ty::new_error(self.tcx, guar));
-                return Err(MethodError::NoMatch(NoMatchData {
-                    static_candidates: Vec::new(),
-                    unsatisfied_predicates: Vec::new(),
-                    out_of_scope_traits: Vec::new(),
-                    similar_candidate: None,
-                    mode,
-                }));
+                return Err(MethodError::ErrorReported(guar));
             }
         }
 
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index e03be4f43f7..a37e9744293 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -229,20 +229,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         match error {
-            MethodError::NoMatch(mut no_match_data) => {
-                return self.report_no_match_method_error(
-                    span,
-                    rcvr_ty,
-                    item_name,
-                    call_id,
-                    source,
-                    args,
-                    sugg_span,
-                    &mut no_match_data,
-                    expected,
-                    trait_missing_method,
-                );
-            }
+            MethodError::NoMatch(mut no_match_data) => self.report_no_match_method_error(
+                span,
+                rcvr_ty,
+                item_name,
+                call_id,
+                source,
+                args,
+                sugg_span,
+                &mut no_match_data,
+                expected,
+                trait_missing_method,
+            ),
 
             MethodError::Ambiguity(mut sources) => {
                 let mut err = struct_span_code_err!(
@@ -263,7 +261,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     &mut sources,
                     Some(sugg_span),
                 );
-                return err.emit();
+                err.emit()
             }
 
             MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
@@ -284,7 +282,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .unwrap_or_else(|| self.tcx.def_span(def_id));
                 err.span_label(sp, format!("private {kind} defined here"));
                 self.suggest_valid_traits(&mut err, item_name, out_of_scope_traits, true);
-                return err.emit();
+                err.emit()
             }
 
             MethodError::IllegalSizedBound { candidates, needs_mut, bound_span, self_expr } => {
@@ -383,9 +381,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                 }
-                return err.emit();
+                err.emit()
             }
 
+            MethodError::ErrorReported(guar) => guar,
+
             MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
         }
     }
diff --git a/tests/ui/methods/dont-suggest-import-on-deref-err.rs b/tests/ui/methods/dont-suggest-import-on-deref-err.rs
new file mode 100644
index 00000000000..c24ab791982
--- /dev/null
+++ b/tests/ui/methods/dont-suggest-import-on-deref-err.rs
@@ -0,0 +1,13 @@
+use std::clone::Clone;
+use std::ops::Deref;
+
+#[derive(Clone)]
+pub struct Foo {}
+
+impl Deref for Foo {}
+//~^ ERROR not all trait items implemented
+
+pub fn main() {
+    let f = Foo {};
+    let _ = f.clone();
+}
diff --git a/tests/ui/methods/dont-suggest-import-on-deref-err.stderr b/tests/ui/methods/dont-suggest-import-on-deref-err.stderr
new file mode 100644
index 00000000000..20a63ff375d
--- /dev/null
+++ b/tests/ui/methods/dont-suggest-import-on-deref-err.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `Target`, `deref`
+  --> $DIR/dont-suggest-import-on-deref-err.rs:7:1
+   |
+LL | impl Deref for Foo {}
+   | ^^^^^^^^^^^^^^^^^^ missing `Target`, `deref` in implementation
+   |
+   = help: implement the missing item: `type Target = /* Type */;`
+   = help: implement the missing item: `fn deref(&self) -> &<Self as Deref>::Target { todo!() }`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0046`.