Skip to content

Commit 6a17ee6

Browse files
committed
Recommend fix count() -> len() on slices
Fixes #87302
1 parent 311fa1f commit 6a17ee6

File tree

4 files changed

+68
-3
lines changed

4 files changed

+68
-3
lines changed

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ symbols! {
496496
core_panic_macro,
497497
cosf32,
498498
cosf64,
499+
count,
499500
cr,
500501
crate_id,
501502
crate_in_paths,

compiler/rustc_typeck/src/check/method/suggest.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6767
}
6868
}
6969

70+
fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
71+
self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
72+
}
73+
7074
pub fn report_method_error(
7175
&self,
7276
mut span: Span,
@@ -691,7 +695,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
691695

692696
let mut restrict_type_params = false;
693697
let mut unsatisfied_bounds = false;
694-
if !unsatisfied_predicates.is_empty() {
698+
if item_name.name == sym::count && self.is_slice_ty(actual, span) {
699+
let msg = "consider using `len` instead";
700+
if let SelfSource::MethodCall(_expr) = source {
701+
err.span_suggestion_short(
702+
span,
703+
msg,
704+
String::from("len"),
705+
Applicability::MachineApplicable,
706+
);
707+
} else {
708+
err.span_label(span, msg);
709+
}
710+
if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
711+
let iterator_trait = self.tcx.def_path_str(iterator_trait);
712+
err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
713+
}
714+
} else if !unsatisfied_predicates.is_empty() {
695715
let def_span = |def_id| {
696716
self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
697717
};
@@ -990,9 +1010,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9901010
}
9911011
}
9921012

993-
let mut fallback_span = true;
994-
let msg = "remove this method call";
9951013
if item_name.name == sym::as_str && actual.peel_refs().is_str() {
1014+
let msg = "remove this method call";
1015+
let mut fallback_span = true;
9961016
if let SelfSource::MethodCall(expr) = source {
9971017
let call_expr =
9981018
self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));

src/test/ui/suggestions/count2len.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn main() {
2+
let slice = [1,2,3,4];
3+
let vec = vec![1,2,3,4];
4+
5+
slice.count(); //~ERROR: E0599
6+
vec.count(); //~ERROR: E0599
7+
vec.as_slice().count(); //~ERROR: E0599
8+
}
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
error[E0599]: no method named `count` found for array `[{integer}; 4]` in the current scope
2+
--> $DIR/count2len.rs:5:11
3+
|
4+
LL | slice.count();
5+
| ^^^^^
6+
| |
7+
| method cannot be called on `[{integer}; 4]` due to unsatisfied trait bounds
8+
| help: consider using `len` instead
9+
|
10+
= note: `count` is defined on `Iterator`, which `[{integer}; 4]` does not implement
11+
12+
error[E0599]: no method named `count` found for struct `Vec<{integer}>` in the current scope
13+
--> $DIR/count2len.rs:6:9
14+
|
15+
LL | vec.count();
16+
| ^^^^^
17+
| |
18+
| method cannot be called on `Vec<{integer}>` due to unsatisfied trait bounds
19+
| help: consider using `len` instead
20+
|
21+
= note: `count` is defined on `Iterator`, which `Vec<{integer}>` does not implement
22+
23+
error[E0599]: no method named `count` found for reference `&[{integer}]` in the current scope
24+
--> $DIR/count2len.rs:7:20
25+
|
26+
LL | vec.as_slice().count();
27+
| ^^^^^
28+
| |
29+
| method cannot be called on `&[{integer}]` due to unsatisfied trait bounds
30+
| help: consider using `len` instead
31+
|
32+
= note: `count` is defined on `Iterator`, which `&[{integer}]` does not implement
33+
34+
error: aborting due to 3 previous errors
35+
36+
For more information about this error, try `rustc --explain E0599`.

0 commit comments

Comments
 (0)