use std::collections::VecDeque;
use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_lint_allowed;
use itertools::{izip, Itertools};
use rustc_ast::{walk_list, Label, Mutability};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_hir::intravisit::{walk_expr, walk_stmt, FnKind, Visitor};
use rustc_hir::{
- Arm, Block, Body, Expr, ExprKind, Guard, HirId, ImplicitSelfKind, Let, Local, Pat, PatKind, Path, PathSegment,
- QPath, Stmt, StmtKind, TyKind, UnOp,
+ Arm, Block, Body, Closure, Expr, ExprKind, Guard, HirId, ImplicitSelfKind, Let, Local, Pat, PatKind, Path,
+ PathSegment, QPath, Stmt, StmtKind, TyKind, UnOp,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
/// and the assigned variables are also only in recursion, it is useless.
///
/// ### Known problems
+ /// Too many code paths in the linting code are currently untested and prone to produce false
+ /// positives or are prone to have performance implications.
+ ///
/// In some cases, this would not catch all useless arguments.
///
/// ```rust
/// # print!("{}", f(1));
/// # }
/// ```
- #[clippy::version = "1.60.0"]
+ #[clippy::version = "1.61.0"]
pub ONLY_USED_IN_RECURSION,
- complexity,
+ nursery,
"arguments that is only used in recursion can be removed"
}
declare_lint_pass!(OnlyUsedInRecursion => [ONLY_USED_IN_RECURSION]);
_: Span,
id: HirId,
) {
+ if is_lint_allowed(cx, ONLY_USED_IN_RECURSION, id) {
+ return;
+ }
if let FnKind::ItemFn(ident, ..) | FnKind::Method(ident, ..) = kind {
let def_id = id.owner.to_def_id();
let data = cx.tcx.def_path(def_id).data;
},
ExprKind::Match(expr, arms, _) => self.visit_match(expr, arms),
// since analysing the closure is not easy, just set all variables in it to side-effect
- ExprKind::Closure(_, _, body_id, _, _) => {
- let body = self.tcx.hir().body(body_id);
+ ExprKind::Closure(&Closure { body, .. }) => {
+ let body = self.tcx.hir().body(body);
self.visit_body(body);
let vars = std::mem::take(&mut self.ret_vars);
self.add_side_effect(vars);
let mut vars = std::mem::take(&mut self.ret_vars);
let _ = arm.guard.as_ref().map(|guard| {
self.visit_expr(match guard {
- Guard::If(expr) | Guard::IfLet(_, expr) => expr,
+ Guard::If(expr) | Guard::IfLet(Let { init: expr, .. }) => expr,
});
vars.append(&mut self.ret_vars);
});