@@ -44,6 +44,7 @@ mod option_as_ref_deref;
4444mod option_map_or_none;
4545mod option_map_unwrap_or;
4646mod or_fun_call;
47+ mod ref_mut_iter_method_chain;
4748mod search_is_some;
4849mod single_char_add_str;
4950mod single_char_insert_string;
@@ -1796,6 +1797,30 @@ declare_clippy_lint! {
17961797 "replace `.splitn(2, pat)` with `.split_once(pat)`"
17971798}
17981799
1800+ declare_clippy_lint ! {
1801+ /// ### What it does
1802+ /// Check for `&mut iter` followed by a method call.
1803+ ///
1804+ /// ### Why is this bad?
1805+ /// This requires using parenthesis to signify precedence.
1806+ ///
1807+ /// ### Example
1808+ /// ```rust
1809+ /// let mut iter = ['a', 'b', '.', 'd'].into_iter();
1810+ /// let before_dot = (&mut iter).take_while(|&c| c != '.').collect::<Vec<_>>();
1811+ /// let after_dot = iter.collect::<Vec<_>>();
1812+ /// ```
1813+ /// Use instead:
1814+ /// ```rust
1815+ /// let mut iter = ['a', 'b', '.', 'd'].into_iter();
1816+ /// let before_dot = iter.by_ref().take_while(|&c| c != '.').collect::<Vec<_>>();
1817+ /// let after_dot = iter.collect::<Vec<_>>();
1818+ /// ```
1819+ pub REF_MUT_ITER_METHOD_CHAIN ,
1820+ style,
1821+ "`&mut iter` used in a method chain"
1822+ }
1823+
17991824pub struct Methods {
18001825 avoid_breaking_exported_api : bool ,
18011826 msrv : Option < RustcVersion > ,
@@ -1874,7 +1899,8 @@ impl_lint_pass!(Methods => [
18741899 SUSPICIOUS_SPLITN ,
18751900 MANUAL_STR_REPEAT ,
18761901 EXTEND_WITH_DRAIN ,
1877- MANUAL_SPLIT_ONCE
1902+ MANUAL_SPLIT_ONCE ,
1903+ REF_MUT_ITER_METHOD_CHAIN
18781904] ) ;
18791905
18801906/// Extracts a method call name, args, and `Span` of the method name.
@@ -1908,7 +1934,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
19081934 hir:: ExprKind :: Call ( func, args) => {
19091935 from_iter_instead_of_collect:: check ( cx, expr, args, func) ;
19101936 } ,
1911- hir:: ExprKind :: MethodCall ( method_call, ref method_span, args, _) => {
1937+ hir:: ExprKind :: MethodCall ( method_call, ref method_span, args @ [ self_arg , .. ] , _) => {
19121938 or_fun_call:: check ( cx, expr, * method_span, & method_call. ident . as_str ( ) , args) ;
19131939 expect_fun_call:: check ( cx, expr, * method_span, & method_call. ident . as_str ( ) , args) ;
19141940 clone_on_copy:: check ( cx, expr, method_call. ident . name , args) ;
@@ -1917,6 +1943,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
19171943 single_char_add_str:: check ( cx, expr, args) ;
19181944 into_iter_on_ref:: check ( cx, expr, * method_span, method_call. ident . name , args) ;
19191945 single_char_pattern:: check ( cx, expr, method_call. ident . name , args) ;
1946+ ref_mut_iter_method_chain:: check ( cx, self_arg) ;
19201947 } ,
19211948 hir:: ExprKind :: Binary ( op, lhs, rhs) if op. node == hir:: BinOpKind :: Eq || op. node == hir:: BinOpKind :: Ne => {
19221949 let mut info = BinaryExprInfo {
0 commit comments