@@ -737,6 +737,25 @@ declare_clippy_lint! {
737
737
"getting the inner pointer of a temporary `CString`"
738
738
}
739
739
740
+ declare_clippy_lint ! {
741
+ /// **What it does:** Checks for calling `.step_by(0)` on iterators which panics.
742
+ ///
743
+ /// **Why is this bad?** This very much looks like an oversight. Use `panic!()` instead if you
744
+ /// actually intend to panic.
745
+ ///
746
+ /// **Known problems:** None.
747
+ ///
748
+ /// **Example:**
749
+ /// ```should_panic
750
+ /// for x in (0..100).step_by(0) {
751
+ /// //..
752
+ /// }
753
+ /// ```
754
+ pub ITERATOR_STEP_BY_ZERO ,
755
+ correctness,
756
+ "using `Iterator::step_by(0)`, which will panic at runtime"
757
+ }
758
+
740
759
declare_clippy_lint ! {
741
760
/// **What it does:** Checks for use of `.iter().nth()` (and the related
742
761
/// `.iter_mut().nth()`) on standard library types with O(1) element access.
@@ -958,11 +977,11 @@ declare_clippy_lint! {
958
977
/// ```
959
978
///
960
979
/// ```rust
961
- /// let _ = (0..4).filter_map(i32::checked_abs );
980
+ /// let _ = (0..4).filter_map(|x| Some(x + 1) );
962
981
/// ```
963
982
/// As there is no conditional check on the argument this could be written as:
964
983
/// ```rust
965
- /// let _ = (0..4).map(i32::checked_abs );
984
+ /// let _ = (0..4).map(|x| x + 1 );
966
985
/// ```
967
986
pub UNNECESSARY_FILTER_MAP ,
968
987
complexity,
@@ -1115,6 +1134,7 @@ declare_lint_pass!(Methods => [
1115
1134
FLAT_MAP_IDENTITY ,
1116
1135
FIND_MAP ,
1117
1136
MAP_FLATTEN ,
1137
+ ITERATOR_STEP_BY_ZERO ,
1118
1138
ITER_NTH ,
1119
1139
ITER_SKIP_NEXT ,
1120
1140
GET_UNWRAP ,
@@ -1173,6 +1193,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
1173
1193
} ,
1174
1194
[ "nth" , "iter" ] => lint_iter_nth ( cx, expr, arg_lists[ 1 ] , false ) ,
1175
1195
[ "nth" , "iter_mut" ] => lint_iter_nth ( cx, expr, arg_lists[ 1 ] , true ) ,
1196
+ [ "step_by" , ..] => lint_step_by ( cx, expr, arg_lists[ 0 ] ) ,
1176
1197
[ "next" , "skip" ] => lint_iter_skip_next ( cx, expr) ,
1177
1198
[ "collect" , "cloned" ] => lint_iter_cloned_collect ( cx, expr, arg_lists[ 1 ] ) ,
1178
1199
[ "as_ref" ] => lint_asref ( cx, expr, "as_ref" , arg_lists[ 0 ] ) ,
@@ -1595,7 +1616,7 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span:
1595
1616
return ;
1596
1617
}
1597
1618
1598
- let receiver_type = cx. tables . expr_ty ( & args[ 0 ] ) ;
1619
+ let receiver_type = cx. tables . expr_ty_adjusted ( & args[ 0 ] ) ;
1599
1620
let closure_args = if match_type ( cx, receiver_type, & paths:: OPTION ) {
1600
1621
"||"
1601
1622
} else if match_type ( cx, receiver_type, & paths:: RESULT ) {
@@ -1950,6 +1971,20 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args:
1950
1971
}
1951
1972
}
1952
1973
1974
+ fn lint_step_by < ' a , ' tcx > ( cx : & LateContext < ' a , ' tcx > , expr : & hir:: Expr , args : & ' tcx [ hir:: Expr ] ) {
1975
+ if match_trait_method ( cx, expr, & paths:: ITERATOR ) {
1976
+ use crate :: consts:: { constant, Constant } ;
1977
+ if let Some ( ( Constant :: Int ( 0 ) , _) ) = constant ( cx, cx. tables , & args[ 1 ] ) {
1978
+ span_lint (
1979
+ cx,
1980
+ ITERATOR_STEP_BY_ZERO ,
1981
+ expr. span ,
1982
+ "Iterator::step_by(0) will panic at runtime" ,
1983
+ ) ;
1984
+ }
1985
+ }
1986
+ }
1987
+
1953
1988
fn lint_iter_nth < ' a , ' tcx > ( cx : & LateContext < ' a , ' tcx > , expr : & hir:: Expr , iter_args : & ' tcx [ hir:: Expr ] , is_mut : bool ) {
1954
1989
let mut_str = if is_mut { "_mut" } else { "" } ;
1955
1990
let caller_type = if derefs_to_slice ( cx, & iter_args[ 0 ] , cx. tables . expr_ty ( & iter_args[ 0 ] ) ) . is_some ( ) {
@@ -2789,8 +2824,8 @@ fn ty_has_iter_method(cx: &LateContext<'_, '_>, self_ref_ty: Ty<'_>) -> Option<(
2789
2824
_ => unreachable ! ( ) ,
2790
2825
} ;
2791
2826
let method_name = match mutbl {
2792
- hir:: Mutability :: Immutable => "iter" ,
2793
- hir:: Mutability :: Mutable => "iter_mut" ,
2827
+ hir:: Mutability :: Not => "iter" ,
2828
+ hir:: Mutability :: Mut => "iter_mut" ,
2794
2829
} ;
2795
2830
( ty_name, method_name)
2796
2831
} )
@@ -2980,8 +3015,8 @@ impl SelfKind {
2980
3015
}
2981
3016
2982
3017
let trait_path = match mutability {
2983
- hir:: Mutability :: Immutable => & paths:: ASREF_TRAIT ,
2984
- hir:: Mutability :: Mutable => & paths:: ASMUT_TRAIT ,
3018
+ hir:: Mutability :: Not => & paths:: ASREF_TRAIT ,
3019
+ hir:: Mutability :: Mut => & paths:: ASMUT_TRAIT ,
2985
3020
} ;
2986
3021
2987
3022
let trait_def_id = match get_trait_def_id ( cx, trait_path) {
@@ -2993,10 +3028,8 @@ impl SelfKind {
2993
3028
2994
3029
match self {
2995
3030
Self :: Value => matches_value ( parent_ty, ty) ,
2996
- Self :: Ref => {
2997
- matches_ref ( cx, hir:: Mutability :: Immutable , parent_ty, ty) || ty == parent_ty && is_copy ( cx, ty)
2998
- } ,
2999
- Self :: RefMut => matches_ref ( cx, hir:: Mutability :: Mutable , parent_ty, ty) ,
3031
+ Self :: Ref => matches_ref ( cx, hir:: Mutability :: Not , parent_ty, ty) || ty == parent_ty && is_copy ( cx, ty) ,
3032
+ Self :: RefMut => matches_ref ( cx, hir:: Mutability :: Mut , parent_ty, ty) ,
3000
3033
Self :: No => ty != parent_ty,
3001
3034
}
3002
3035
}
0 commit comments