Skip to content

Commit 69161c6

Browse files
committed
fix to lint Self::function
1 parent e476677 commit 69161c6

File tree

3 files changed

+80
-39
lines changed

3 files changed

+80
-39
lines changed

clippy_lints/src/only_used_in_recursion.rs

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ use itertools::{izip, Itertools};
55
use rustc_ast::{walk_list, Label, Mutability};
66
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
77
use rustc_errors::Applicability;
8-
use rustc_hir::def::Res;
8+
use rustc_hir::def::{DefKind, Res};
9+
use rustc_hir::def_id::DefId;
910
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
1011
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
1112
use rustc_hir::{
12-
Arm, Block, Body, Expr, ExprKind, Guard, HirId, Let, Local, Pat, PatKind, Path, PathSegment, QPath, Stmt, StmtKind,
13-
UnOp,
13+
Arm, Block, Body, Expr, ExprKind, Guard, HirId, ImplicitSelfKind, Let, Local, Pat, PatKind, Path, PathSegment,
14+
QPath, Stmt, StmtKind, TyKind, UnOp,
1415
};
1516
use rustc_lint::{LateContext, LateLintPass};
1617
use rustc_middle::ty;
@@ -94,13 +95,15 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
9495
&mut self,
9596
cx: &LateContext<'tcx>,
9697
kind: FnKind<'tcx>,
97-
_: &'tcx rustc_hir::FnDecl<'tcx>,
98+
decl: &'tcx rustc_hir::FnDecl<'tcx>,
9899
body: &'tcx Body<'tcx>,
99100
_: Span,
100101
id: HirId,
101102
) {
102103
if let FnKind::ItemFn(ident, ..) | FnKind::Method(ident, ..) = kind {
103-
let data = cx.tcx.def_path(cx.tcx.hir().local_def_id(id).to_def_id()).data;
104+
let def_id = id.owner.to_def_id();
105+
let data = cx.tcx.def_path(def_id).data;
106+
104107
if data.len() > 1 {
105108
match data.get(data.len() - 2) {
106109
Some(DisambiguatedDefPathData {
@@ -111,6 +114,8 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
111114
}
112115
}
113116

117+
let has_self = !matches!(decl.implicit_self, ImplicitSelfKind::None);
118+
114119
let ty_res = cx.typeck_results();
115120
let param_span = body
116121
.params
@@ -122,10 +127,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
122127
});
123128
v
124129
})
125-
.skip(match kind {
126-
FnKind::Method(..) => 1,
127-
_ => 0,
128-
})
130+
.skip(if has_self { 1 } else { 0 })
129131
.filter(|(_, _, ident)| !ident.name.as_str().starts_with('_'))
130132
.collect_vec();
131133

@@ -139,7 +141,9 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
139141
break_vars: FxHashMap::default(),
140142
params,
141143
fn_ident: ident,
144+
fn_def_id: def_id,
142145
is_method: matches!(kind, FnKind::Method(..)),
146+
has_self,
143147
ty_res,
144148
ty_ctx: cx.tcx,
145149
};
@@ -242,7 +246,9 @@ pub struct SideEffectVisit<'tcx> {
242246
break_vars: FxHashMap<Ident, Vec<(HirId, bool)>>,
243247
params: Vec<&'tcx Pat<'tcx>>,
244248
fn_ident: Ident,
249+
fn_def_id: DefId,
245250
is_method: bool,
251+
has_self: bool,
246252
ty_res: &'tcx TypeckResults<'tcx>,
247253
ty_ctx: TyCtxt<'tcx>,
248254
}
@@ -479,41 +485,55 @@ impl<'tcx> SideEffectVisit<'tcx> {
479485
let mut ret_vars = std::mem::take(&mut self.ret_vars);
480486
self.add_side_effect(ret_vars.clone());
481487

488+
let mut is_recursive = false;
489+
482490
if_chain! {
483-
if !self.is_method;
491+
if !self.has_self;
484492
if let ExprKind::Path(QPath::Resolved(_, path)) = callee.kind;
485-
if let Res::Def(..) = path.res;
486-
if path.segments.len() == 1;
487-
let ident = path.segments.last().unwrap().ident;
488-
if ident == self.fn_ident;
493+
if let Res::Def(DefKind::Fn, def_id) = path.res;
494+
if self.fn_def_id == def_id;
489495
then {
490-
izip!(self.params.clone(), args)
491-
.for_each(|(pat, expr)| {
492-
self.visit_pat_expr(pat, expr, true);
493-
self.ret_vars.clear();
494-
});
495-
} else {
496-
// This would set arguments used in closure that does not have side-effect.
497-
// Closure itself can be detected whether there is a side-effect, but the
498-
// value of variable that is holding closure can change.
499-
// So, we just check the variables.
500-
self.ret_vars = args
501-
.iter()
502-
.flat_map(|expr| {
503-
self.visit_expr(expr);
504-
std::mem::take(&mut self.ret_vars)
505-
})
506-
.collect_vec()
507-
.into_iter()
508-
.map(|id| {
509-
self.has_side_effect.insert(id.0);
510-
id
511-
})
512-
.collect();
513-
self.contains_side_effect = true;
496+
is_recursive = true;
497+
}
498+
}
499+
500+
if_chain! {
501+
if !self.has_self && self.is_method;
502+
if let ExprKind::Path(QPath::TypeRelative(ty, segment)) = callee.kind;
503+
if segment.ident == self.fn_ident;
504+
if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind;
505+
if let Res::SelfTy(..) = path.res;
506+
then {
507+
is_recursive = true;
514508
}
515509
}
516510

511+
if is_recursive {
512+
izip!(self.params.clone(), args).for_each(|(pat, expr)| {
513+
self.visit_pat_expr(pat, expr, true);
514+
self.ret_vars.clear();
515+
});
516+
} else {
517+
// This would set arguments used in closure that does not have side-effect.
518+
// Closure itself can be detected whether there is a side-effect, but the
519+
// value of variable that is holding closure can change.
520+
// So, we just check the variables.
521+
self.ret_vars = args
522+
.iter()
523+
.flat_map(|expr| {
524+
self.visit_expr(expr);
525+
std::mem::take(&mut self.ret_vars)
526+
})
527+
.collect_vec()
528+
.into_iter()
529+
.map(|id| {
530+
self.has_side_effect.insert(id.0);
531+
id
532+
})
533+
.collect();
534+
self.contains_side_effect = true;
535+
}
536+
517537
self.ret_vars.append(&mut ret_vars);
518538
}
519539

tests/ui/only_used_in_recursion.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,19 @@ fn ignore2(a: usize, _b: usize) -> usize {
104104
if a == 1 { 1 } else { ignore2(a - 1, _b) }
105105
}
106106

107+
fn f1(a: u32) -> u32 {
108+
a
109+
}
110+
111+
fn f2(a: u32) -> u32 {
112+
f1(a)
113+
}
114+
115+
fn inner_fn(a: u32) -> u32 {
116+
fn inner_fn(a: u32) -> u32 {
117+
a
118+
}
119+
inner_fn(a)
120+
}
121+
107122
fn main() {}

tests/ui/only_used_in_recursion.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,17 @@ error: parameter is only used in recursion
6666
LL | fn method2(&self, a: usize, b: usize) -> usize {
6767
| ^ help: if this is intentional, prefix with an underscore: `_b`
6868

69+
error: parameter is only used in recursion
70+
--> $DIR/only_used_in_recursion.rs:90:24
71+
|
72+
LL | fn hello(a: usize, b: usize) -> usize {
73+
| ^ help: if this is intentional, prefix with an underscore: `_b`
74+
6975
error: parameter is only used in recursion
7076
--> $DIR/only_used_in_recursion.rs:94:32
7177
|
7278
LL | fn hello2(&self, a: usize, b: usize) -> usize {
7379
| ^ help: if this is intentional, prefix with an underscore: `_b`
7480

75-
error: aborting due to 12 previous errors
81+
error: aborting due to 13 previous errors
7682

0 commit comments

Comments
 (0)