@@ -737,6 +737,25 @@ declare_clippy_lint! {
737737 "getting the inner pointer of a temporary `CString`"
738738}
739739
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+
740759declare_clippy_lint ! {
741760 /// **What it does:** Checks for use of `.iter().nth()` (and the related
742761 /// `.iter_mut().nth()`) on standard library types with O(1) element access.
@@ -958,11 +977,11 @@ declare_clippy_lint! {
958977 /// ```
959978 ///
960979 /// ```rust
961- /// let _ = (0..4).filter_map(i32::checked_abs );
980+ /// let _ = (0..4).filter_map(|x| Some(x + 1) );
962981 /// ```
963982 /// As there is no conditional check on the argument this could be written as:
964983 /// ```rust
965- /// let _ = (0..4).map(i32::checked_abs );
984+ /// let _ = (0..4).map(|x| x + 1 );
966985 /// ```
967986 pub UNNECESSARY_FILTER_MAP ,
968987 complexity,
@@ -1115,6 +1134,7 @@ declare_lint_pass!(Methods => [
11151134 FLAT_MAP_IDENTITY ,
11161135 FIND_MAP ,
11171136 MAP_FLATTEN ,
1137+ ITERATOR_STEP_BY_ZERO ,
11181138 ITER_NTH ,
11191139 ITER_SKIP_NEXT ,
11201140 GET_UNWRAP ,
@@ -1173,6 +1193,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
11731193 } ,
11741194 [ "nth" , "iter" ] => lint_iter_nth ( cx, expr, arg_lists[ 1 ] , false ) ,
11751195 [ "nth" , "iter_mut" ] => lint_iter_nth ( cx, expr, arg_lists[ 1 ] , true ) ,
1196+ [ "step_by" , ..] => lint_step_by ( cx, expr, arg_lists[ 0 ] ) ,
11761197 [ "next" , "skip" ] => lint_iter_skip_next ( cx, expr) ,
11771198 [ "collect" , "cloned" ] => lint_iter_cloned_collect ( cx, expr, arg_lists[ 1 ] ) ,
11781199 [ "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:
15951616 return ;
15961617 }
15971618
1598- let receiver_type = cx. tables . expr_ty ( & args[ 0 ] ) ;
1619+ let receiver_type = cx. tables . expr_ty_adjusted ( & args[ 0 ] ) ;
15991620 let closure_args = if match_type ( cx, receiver_type, & paths:: OPTION ) {
16001621 "||"
16011622 } else if match_type ( cx, receiver_type, & paths:: RESULT ) {
@@ -1950,6 +1971,20 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args:
19501971 }
19511972}
19521973
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+
19531988fn lint_iter_nth < ' a , ' tcx > ( cx : & LateContext < ' a , ' tcx > , expr : & hir:: Expr , iter_args : & ' tcx [ hir:: Expr ] , is_mut : bool ) {
19541989 let mut_str = if is_mut { "_mut" } else { "" } ;
19551990 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<(
27892824 _ => unreachable ! ( ) ,
27902825 } ;
27912826 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" ,
27942829 } ;
27952830 ( ty_name, method_name)
27962831 } )
@@ -2980,8 +3015,8 @@ impl SelfKind {
29803015 }
29813016
29823017 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 ,
29853020 } ;
29863021
29873022 let trait_def_id = match get_trait_def_id ( cx, trait_path) {
@@ -2993,10 +3028,8 @@ impl SelfKind {
29933028
29943029 match self {
29953030 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) ,
30003033 Self :: No => ty != parent_ty,
30013034 }
30023035 }
0 commit comments