about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2021-12-07 11:04:56 +0100
committerGitHub <noreply@github.com>2021-12-07 11:04:56 +0100
commitf84a734a8ea3fdd9abe0217797d7a07f31bb8ee8 (patch)
tree33ba9bdc1652a7539b5161de2b4c66b1389e4465
parent2af5c6562deed1878000e791f2cb21b981a53959 (diff)
parent6a17ee6d4125c0c35147b16ebcf54e34f0cdc87a (diff)
downloadrust-f84a734a8ea3fdd9abe0217797d7a07f31bb8ee8.tar.gz
rust-f84a734a8ea3fdd9abe0217797d7a07f31bb8ee8.zip
Rollup merge of #87614 - notriddle:notriddle-count2len, r=Mark-Simulacrum
Recommend fix `count()` -> `len()` on slices

Fixes #87302
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs26
-rw-r--r--src/test/ui/suggestions/count2len.rs8
-rw-r--r--src/test/ui/suggestions/count2len.stderr36
4 files changed, 68 insertions, 3 deletions
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 309c305293f..49947cc1fa4 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -499,6 +499,7 @@ symbols! {
         core_panic_macro,
         cosf32,
         cosf64,
+        count,
         cr,
         crate_id,
         crate_in_paths,
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index ca174ed5e84..ad38885dbd8 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -67,6 +67,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
+        self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
+    }
+
     pub fn report_method_error(
         &self,
         mut span: Span,
@@ -691,7 +695,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 let mut restrict_type_params = false;
                 let mut unsatisfied_bounds = false;
-                if !unsatisfied_predicates.is_empty() {
+                if item_name.name == sym::count && self.is_slice_ty(actual, span) {
+                    let msg = "consider using `len` instead";
+                    if let SelfSource::MethodCall(_expr) = source {
+                        err.span_suggestion_short(
+                            span,
+                            msg,
+                            String::from("len"),
+                            Applicability::MachineApplicable,
+                        );
+                    } else {
+                        err.span_label(span, msg);
+                    }
+                    if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
+                        let iterator_trait = self.tcx.def_path_str(iterator_trait);
+                        err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
+                    }
+                } else if !unsatisfied_predicates.is_empty() {
                     let def_span = |def_id| {
                         self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
                     };
@@ -990,9 +1010,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 }
 
-                let mut fallback_span = true;
-                let msg = "remove this method call";
                 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
+                    let msg = "remove this method call";
+                    let mut fallback_span = true;
                     if let SelfSource::MethodCall(expr) = source {
                         let call_expr =
                             self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
diff --git a/src/test/ui/suggestions/count2len.rs b/src/test/ui/suggestions/count2len.rs
new file mode 100644
index 00000000000..f11a789efbc
--- /dev/null
+++ b/src/test/ui/suggestions/count2len.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let slice = [1,2,3,4];
+    let vec = vec![1,2,3,4];
+
+    slice.count(); //~ERROR: E0599
+    vec.count(); //~ERROR: E0599
+    vec.as_slice().count(); //~ERROR: E0599
+}
diff --git a/src/test/ui/suggestions/count2len.stderr b/src/test/ui/suggestions/count2len.stderr
new file mode 100644
index 00000000000..6394a84dd47
--- /dev/null
+++ b/src/test/ui/suggestions/count2len.stderr
@@ -0,0 +1,36 @@
+error[E0599]: no method named `count` found for array `[{integer}; 4]` in the current scope
+  --> $DIR/count2len.rs:5:11
+   |
+LL |     slice.count();
+   |           ^^^^^
+   |           |
+   |           method cannot be called on `[{integer}; 4]` due to unsatisfied trait bounds
+   |           help: consider using `len` instead
+   |
+   = note: `count` is defined on `Iterator`, which `[{integer}; 4]` does not implement
+
+error[E0599]: no method named `count` found for struct `Vec<{integer}>` in the current scope
+  --> $DIR/count2len.rs:6:9
+   |
+LL |     vec.count();
+   |         ^^^^^
+   |         |
+   |         method cannot be called on `Vec<{integer}>` due to unsatisfied trait bounds
+   |         help: consider using `len` instead
+   |
+   = note: `count` is defined on `Iterator`, which `Vec<{integer}>` does not implement
+
+error[E0599]: no method named `count` found for reference `&[{integer}]` in the current scope
+  --> $DIR/count2len.rs:7:20
+   |
+LL |     vec.as_slice().count();
+   |                    ^^^^^
+   |                    |
+   |                    method cannot be called on `&[{integer}]` due to unsatisfied trait bounds
+   |                    help: consider using `len` instead
+   |
+   = note: `count` is defined on `Iterator`, which `&[{integer}]` does not implement
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0599`.