1
- use clippy_utils:: diagnostics:: span_lint_and_note;
1
+ use clippy_utils:: diagnostics:: span_lint_and_sugg;
2
+ use clippy_utils:: source:: snippet_with_applicability;
3
+ use clippy_utils:: ty:: is_type_diagnostic_item;
4
+ use clippy_utils:: { match_def_path, paths} ;
2
5
use if_chain:: if_chain;
6
+ use rustc_errors:: Applicability ;
3
7
use rustc_hir as hir;
4
8
use rustc_lint:: { LateContext , LateLintPass } ;
9
+ use rustc_middle:: ty;
5
10
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
11
+ use rustc_span:: sym;
6
12
7
13
declare_clippy_lint ! {
8
14
/// ### What it does
@@ -16,37 +22,47 @@ declare_clippy_lint! {
16
22
/// ### Example
17
23
/// ```rust
18
24
/// "hello".bytes().count();
25
+ /// String::from("hello").bytes().count();
19
26
/// ```
20
27
/// Use instead:
21
28
/// ```rust
22
29
/// "hello".len();
30
+ /// String::from("hello").len();
23
31
/// ```
24
- #[ clippy:: version = "1.60 .0" ]
32
+ #[ clippy:: version = "1.62 .0" ]
25
33
pub BYTES_COUNT_TO_LEN ,
26
34
complexity,
27
- "Using bytest ().count() when len() performs the same functionality"
35
+ "Using `bytes ().count()` when ` len()` performs the same functionality"
28
36
}
29
37
30
38
declare_lint_pass ! ( BytesCountToLen => [ BYTES_COUNT_TO_LEN ] ) ;
31
39
32
40
impl < ' tcx > LateLintPass < ' tcx > for BytesCountToLen {
33
41
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx hir:: Expr < ' _ > ) {
34
42
if_chain ! {
35
- //check for method call called "count"
36
- if let hir:: ExprKind :: MethodCall ( count_path, count_args, _) = & expr. kind;
37
- if count_path. ident. name == rustc_span:: sym:: count;
38
- if let [ bytes_expr] = & * * count_args;
39
- //check for method call called "bytes" that was linked to "count"
40
- if let hir:: ExprKind :: MethodCall ( bytes_path, _, _) = & bytes_expr. kind;
41
- if bytes_path. ident. name. as_str( ) == "bytes" ;
43
+ if let hir:: ExprKind :: MethodCall ( _, expr_args, _) = & expr. kind;
44
+ if let Some ( expr_def_id) = cx. typeck_results( ) . type_dependent_def_id( expr. hir_id) ;
45
+ if match_def_path( cx, expr_def_id, & paths:: ITER_COUNT ) ;
46
+
47
+ if let [ bytes_expr] = & * * expr_args;
48
+ if let hir:: ExprKind :: MethodCall ( _, bytes_args, _) = & bytes_expr. kind;
49
+ if let Some ( bytes_def_id) = cx. typeck_results( ) . type_dependent_def_id( bytes_expr. hir_id) ;
50
+ if match_def_path( cx, bytes_def_id, & paths:: STR_BYTES ) ;
51
+
52
+ if let [ str_expr] = & * * bytes_args;
53
+ let ty = cx. typeck_results( ) . expr_ty( str_expr) . peel_refs( ) ;
54
+
55
+ if is_type_diagnostic_item( cx, ty, sym:: String ) || ty. kind( ) == & ty:: Str ;
42
56
then {
43
- span_lint_and_note(
57
+ let mut applicability = Applicability :: MachineApplicable ;
58
+ span_lint_and_sugg(
44
59
cx,
45
60
BYTES_COUNT_TO_LEN ,
46
61
expr. span,
47
62
"using long and hard to read `.bytes().count()`" ,
48
- None ,
49
- "`.len()` achieves same functionality"
63
+ "consider calling `.len()` instead" ,
64
+ format!( "{}.len()" , snippet_with_applicability( cx, str_expr. span, ".." , & mut applicability) ) ,
65
+ applicability
50
66
) ;
51
67
}
52
68
} ;
0 commit comments