|
| 1 | +use super::utils::clone_or_copy_needed; |
1 | 2 | use clippy_utils::diagnostics::span_lint_and_then;
|
2 | 3 | use clippy_utils::higher::ForLoop;
|
3 | 4 | use clippy_utils::source::snippet_opt;
|
4 | 5 | use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait};
|
5 |
| -use clippy_utils::{fn_def_id, get_parent_expr, path_to_local_id, usage}; |
| 6 | +use clippy_utils::{fn_def_id, get_parent_expr}; |
6 | 7 | use rustc_errors::Applicability;
|
7 |
| -use rustc_hir::intravisit::{walk_expr, Visitor}; |
8 |
| -use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, HirId, LangItem, Mutability, Pat}; |
| 8 | +use rustc_hir::{def_id::DefId, Expr, ExprKind, LangItem}; |
9 | 9 | use rustc_lint::LateContext;
|
10 |
| -use rustc_middle::hir::nested_filter; |
11 |
| -use rustc_middle::ty; |
12 | 10 | use rustc_span::{sym, Symbol};
|
13 | 11 |
|
14 | 12 | use super::UNNECESSARY_TO_OWNED;
|
@@ -100,89 +98,6 @@ pub fn check_for_loop_iter(
|
100 | 98 | false
|
101 | 99 | }
|
102 | 100 |
|
103 |
| -/// The core logic of `check_for_loop_iter` above, this function wraps a use of |
104 |
| -/// `CloneOrCopyVisitor`. |
105 |
| -fn clone_or_copy_needed<'tcx>( |
106 |
| - cx: &LateContext<'tcx>, |
107 |
| - pat: &Pat<'tcx>, |
108 |
| - body: &'tcx Expr<'tcx>, |
109 |
| -) -> (bool, Vec<&'tcx Expr<'tcx>>) { |
110 |
| - let mut visitor = CloneOrCopyVisitor { |
111 |
| - cx, |
112 |
| - binding_hir_ids: pat_bindings(pat), |
113 |
| - clone_or_copy_needed: false, |
114 |
| - addr_of_exprs: Vec::new(), |
115 |
| - }; |
116 |
| - visitor.visit_expr(body); |
117 |
| - (visitor.clone_or_copy_needed, visitor.addr_of_exprs) |
118 |
| -} |
119 |
| - |
120 |
| -/// Returns a vector of all `HirId`s bound by the pattern. |
121 |
| -fn pat_bindings(pat: &Pat<'_>) -> Vec<HirId> { |
122 |
| - let mut collector = usage::ParamBindingIdCollector { |
123 |
| - binding_hir_ids: Vec::new(), |
124 |
| - }; |
125 |
| - collector.visit_pat(pat); |
126 |
| - collector.binding_hir_ids |
127 |
| -} |
128 |
| - |
129 |
| -/// `clone_or_copy_needed` will be false when `CloneOrCopyVisitor` is done visiting if the only |
130 |
| -/// operations performed on `binding_hir_ids` are: |
131 |
| -/// * to take non-mutable references to them |
132 |
| -/// * to use them as non-mutable `&self` in method calls |
133 |
| -/// If any of `binding_hir_ids` is used in any other way, then `clone_or_copy_needed` will be true |
134 |
| -/// when `CloneOrCopyVisitor` is done visiting. |
135 |
| -struct CloneOrCopyVisitor<'cx, 'tcx> { |
136 |
| - cx: &'cx LateContext<'tcx>, |
137 |
| - binding_hir_ids: Vec<HirId>, |
138 |
| - clone_or_copy_needed: bool, |
139 |
| - addr_of_exprs: Vec<&'tcx Expr<'tcx>>, |
140 |
| -} |
141 |
| - |
142 |
| -impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> { |
143 |
| - type NestedFilter = nested_filter::OnlyBodies; |
144 |
| - |
145 |
| - fn nested_visit_map(&mut self) -> Self::Map { |
146 |
| - self.cx.tcx.hir() |
147 |
| - } |
148 |
| - |
149 |
| - fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { |
150 |
| - walk_expr(self, expr); |
151 |
| - if self.is_binding(expr) { |
152 |
| - if let Some(parent) = get_parent_expr(self.cx, expr) { |
153 |
| - match parent.kind { |
154 |
| - ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, _) => { |
155 |
| - self.addr_of_exprs.push(parent); |
156 |
| - return; |
157 |
| - }, |
158 |
| - ExprKind::MethodCall(_, args, _) => { |
159 |
| - if_chain! { |
160 |
| - if args.iter().skip(1).all(|arg| !self.is_binding(arg)); |
161 |
| - if let Some(method_def_id) = self.cx.typeck_results().type_dependent_def_id(parent.hir_id); |
162 |
| - let method_ty = self.cx.tcx.type_of(method_def_id); |
163 |
| - let self_ty = method_ty.fn_sig(self.cx.tcx).input(0).skip_binder(); |
164 |
| - if matches!(self_ty.kind(), ty::Ref(_, _, Mutability::Not)); |
165 |
| - then { |
166 |
| - return; |
167 |
| - } |
168 |
| - } |
169 |
| - }, |
170 |
| - _ => {}, |
171 |
| - } |
172 |
| - } |
173 |
| - self.clone_or_copy_needed = true; |
174 |
| - } |
175 |
| - } |
176 |
| -} |
177 |
| - |
178 |
| -impl<'cx, 'tcx> CloneOrCopyVisitor<'cx, 'tcx> { |
179 |
| - fn is_binding(&self, expr: &Expr<'tcx>) -> bool { |
180 |
| - self.binding_hir_ids |
181 |
| - .iter() |
182 |
| - .any(|hir_id| path_to_local_id(expr, *hir_id)) |
183 |
| - } |
184 |
| -} |
185 |
| - |
186 | 101 | /// Returns true if the named method is `IntoIterator::into_iter`.
|
187 | 102 | pub fn is_into_iter(cx: &LateContext<'_>, callee_def_id: DefId) -> bool {
|
188 | 103 | cx.tcx.lang_items().require(LangItem::IntoIterIntoIter) == Ok(callee_def_id)
|
|
0 commit comments