|
| 1 | +mod for_loop_arg; |
1 | 2 | mod manual_flatten;
|
2 | 3 | mod utils;
|
3 | 4 |
|
@@ -27,7 +28,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
|
27 | 28 | use rustc_middle::hir::map::Map;
|
28 | 29 | use rustc_middle::lint::in_external_macro;
|
29 | 30 | use rustc_middle::middle::region;
|
30 |
| -use rustc_middle::ty::{self, Ty, TyS}; |
| 31 | +use rustc_middle::ty::{self, Ty}; |
31 | 32 | use rustc_session::{declare_lint_pass, declare_tool_lint};
|
32 | 33 | use rustc_span::source_map::Span;
|
33 | 34 | use rustc_span::symbol::{sym, Ident, Symbol};
|
@@ -861,12 +862,12 @@ fn check_for_loop<'tcx>(
|
861 | 862 | check_for_loop_range(cx, pat, arg, body, expr);
|
862 | 863 | check_for_loop_explicit_counter(cx, pat, arg, body, expr);
|
863 | 864 | }
|
864 |
| - check_for_loop_arg(cx, pat, arg, expr); |
| 865 | + for_loop_arg::check_for_loop_arg(cx, pat, arg, expr); |
865 | 866 | check_for_loop_over_map_kv(cx, pat, arg, body, expr);
|
866 | 867 | check_for_mut_range_bound(cx, arg, body);
|
867 | 868 | check_for_single_element_loop(cx, pat, arg, body, expr);
|
868 | 869 | detect_same_item_push(cx, pat, arg, body, expr);
|
869 |
| - manual_flatten::lint(cx, pat, arg, body, span); |
| 870 | + manual_flatten::check_manual_flatten(cx, pat, arg, body, span); |
870 | 871 | }
|
871 | 872 |
|
872 | 873 | // this function assumes the given expression is a `for` loop.
|
@@ -1682,118 +1683,6 @@ fn is_end_eq_array_len<'tcx>(
|
1682 | 1683 | false
|
1683 | 1684 | }
|
1684 | 1685 |
|
1685 |
| -fn lint_iter_method(cx: &LateContext<'_>, args: &[Expr<'_>], arg: &Expr<'_>, method_name: &str) { |
1686 |
| - let mut applicability = Applicability::MachineApplicable; |
1687 |
| - let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability); |
1688 |
| - let muta = if method_name == "iter_mut" { "mut " } else { "" }; |
1689 |
| - span_lint_and_sugg( |
1690 |
| - cx, |
1691 |
| - EXPLICIT_ITER_LOOP, |
1692 |
| - arg.span, |
1693 |
| - "it is more concise to loop over references to containers instead of using explicit \ |
1694 |
| - iteration methods", |
1695 |
| - "to write this more concisely, try", |
1696 |
| - format!("&{}{}", muta, object), |
1697 |
| - applicability, |
1698 |
| - ) |
1699 |
| -} |
1700 |
| - |
1701 |
| -fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) { |
1702 |
| - let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used |
1703 |
| - if let ExprKind::MethodCall(ref method, _, ref args, _) = arg.kind { |
1704 |
| - // just the receiver, no arguments |
1705 |
| - if args.len() == 1 { |
1706 |
| - let method_name = &*method.ident.as_str(); |
1707 |
| - // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x |
1708 |
| - if method_name == "iter" || method_name == "iter_mut" { |
1709 |
| - if is_ref_iterable_type(cx, &args[0]) { |
1710 |
| - lint_iter_method(cx, args, arg, method_name); |
1711 |
| - } |
1712 |
| - } else if method_name == "into_iter" && match_trait_method(cx, arg, &paths::INTO_ITERATOR) { |
1713 |
| - let receiver_ty = cx.typeck_results().expr_ty(&args[0]); |
1714 |
| - let receiver_ty_adjusted = cx.typeck_results().expr_ty_adjusted(&args[0]); |
1715 |
| - if TyS::same_type(receiver_ty, receiver_ty_adjusted) { |
1716 |
| - let mut applicability = Applicability::MachineApplicable; |
1717 |
| - let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability); |
1718 |
| - span_lint_and_sugg( |
1719 |
| - cx, |
1720 |
| - EXPLICIT_INTO_ITER_LOOP, |
1721 |
| - arg.span, |
1722 |
| - "it is more concise to loop over containers instead of using explicit \ |
1723 |
| - iteration methods", |
1724 |
| - "to write this more concisely, try", |
1725 |
| - object.to_string(), |
1726 |
| - applicability, |
1727 |
| - ); |
1728 |
| - } else { |
1729 |
| - let ref_receiver_ty = cx.tcx.mk_ref( |
1730 |
| - cx.tcx.lifetimes.re_erased, |
1731 |
| - ty::TypeAndMut { |
1732 |
| - ty: receiver_ty, |
1733 |
| - mutbl: Mutability::Not, |
1734 |
| - }, |
1735 |
| - ); |
1736 |
| - if TyS::same_type(receiver_ty_adjusted, ref_receiver_ty) { |
1737 |
| - lint_iter_method(cx, args, arg, method_name) |
1738 |
| - } |
1739 |
| - } |
1740 |
| - } else if method_name == "next" && match_trait_method(cx, arg, &paths::ITERATOR) { |
1741 |
| - span_lint( |
1742 |
| - cx, |
1743 |
| - ITER_NEXT_LOOP, |
1744 |
| - expr.span, |
1745 |
| - "you are iterating over `Iterator::next()` which is an Option; this will compile but is \ |
1746 |
| - probably not what you want", |
1747 |
| - ); |
1748 |
| - next_loop_linted = true; |
1749 |
| - } |
1750 |
| - } |
1751 |
| - } |
1752 |
| - if !next_loop_linted { |
1753 |
| - check_arg_type(cx, pat, arg); |
1754 |
| - } |
1755 |
| -} |
1756 |
| - |
1757 |
| -/// Checks for `for` loops over `Option`s and `Result`s. |
1758 |
| -fn check_arg_type(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) { |
1759 |
| - let ty = cx.typeck_results().expr_ty(arg); |
1760 |
| - if is_type_diagnostic_item(cx, ty, sym::option_type) { |
1761 |
| - span_lint_and_help( |
1762 |
| - cx, |
1763 |
| - FOR_LOOPS_OVER_FALLIBLES, |
1764 |
| - arg.span, |
1765 |
| - &format!( |
1766 |
| - "for loop over `{0}`, which is an `Option`. This is more readably written as an \ |
1767 |
| - `if let` statement", |
1768 |
| - snippet(cx, arg.span, "_") |
1769 |
| - ), |
1770 |
| - None, |
1771 |
| - &format!( |
1772 |
| - "consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`", |
1773 |
| - snippet(cx, pat.span, "_"), |
1774 |
| - snippet(cx, arg.span, "_") |
1775 |
| - ), |
1776 |
| - ); |
1777 |
| - } else if is_type_diagnostic_item(cx, ty, sym::result_type) { |
1778 |
| - span_lint_and_help( |
1779 |
| - cx, |
1780 |
| - FOR_LOOPS_OVER_FALLIBLES, |
1781 |
| - arg.span, |
1782 |
| - &format!( |
1783 |
| - "for loop over `{0}`, which is a `Result`. This is more readably written as an \ |
1784 |
| - `if let` statement", |
1785 |
| - snippet(cx, arg.span, "_") |
1786 |
| - ), |
1787 |
| - None, |
1788 |
| - &format!( |
1789 |
| - "consider replacing `for {0} in {1}` with `if let Ok({0}) = {1}`", |
1790 |
| - snippet(cx, pat.span, "_"), |
1791 |
| - snippet(cx, arg.span, "_") |
1792 |
| - ), |
1793 |
| - ); |
1794 |
| - } |
1795 |
| -} |
1796 |
| - |
1797 | 1686 | // To trigger the EXPLICIT_COUNTER_LOOP lint, a variable must be
|
1798 | 1687 | // incremented exactly once in the loop body, and initialized to zero
|
1799 | 1688 | // at the start of the loop.
|
@@ -2270,34 +2159,6 @@ impl<'tcx> Visitor<'tcx> for VarUsedAfterLoopVisitor {
|
2270 | 2159 | }
|
2271 | 2160 | }
|
2272 | 2161 |
|
2273 |
| -/// Returns `true` if the type of expr is one that provides `IntoIterator` impls |
2274 |
| -/// for `&T` and `&mut T`, such as `Vec`. |
2275 |
| -#[rustfmt::skip] |
2276 |
| -fn is_ref_iterable_type(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { |
2277 |
| - // no walk_ptrs_ty: calling iter() on a reference can make sense because it |
2278 |
| - // will allow further borrows afterwards |
2279 |
| - let ty = cx.typeck_results().expr_ty(e); |
2280 |
| - is_iterable_array(ty, cx) || |
2281 |
| - is_type_diagnostic_item(cx, ty, sym::vec_type) || |
2282 |
| - match_type(cx, ty, &paths::LINKED_LIST) || |
2283 |
| - is_type_diagnostic_item(cx, ty, sym!(hashmap_type)) || |
2284 |
| - is_type_diagnostic_item(cx, ty, sym!(hashset_type)) || |
2285 |
| - is_type_diagnostic_item(cx, ty, sym!(vecdeque_type)) || |
2286 |
| - match_type(cx, ty, &paths::BINARY_HEAP) || |
2287 |
| - match_type(cx, ty, &paths::BTREEMAP) || |
2288 |
| - match_type(cx, ty, &paths::BTREESET) |
2289 |
| -} |
2290 |
| - |
2291 |
| -fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool { |
2292 |
| - // IntoIterator is currently only implemented for array sizes <= 32 in rustc |
2293 |
| - match ty.kind() { |
2294 |
| - ty::Array(_, n) => n |
2295 |
| - .try_eval_usize(cx.tcx, cx.param_env) |
2296 |
| - .map_or(false, |val| (0..=32).contains(&val)), |
2297 |
| - _ => false, |
2298 |
| - } |
2299 |
| -} |
2300 |
| - |
2301 | 2162 | /// If a block begins with a statement (possibly a `let` binding) and has an
|
2302 | 2163 | /// expression, return it.
|
2303 | 2164 | fn extract_expr_from_first_stmt<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> {
|
|
0 commit comments