Skip to content

Commit f9c2407

Browse files
committed
Auto merge of rust-lang#13072 - Jarcho:misc_small5, r=xFrednet
Misc refactorings part 5 `toplevel_ref_arg` gets a small fix so it can be allowed on function arguments. Otherwise just some rearrangements. changelog: none
2 parents 637d39f + 0c72a99 commit f9c2407

11 files changed

+133
-178
lines changed

clippy_lints/src/misc.rs

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clippy_utils::diagnostics::{span_lint, span_lint_and_then, span_lint_hir_and_then};
1+
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir, span_lint_hir_and_then};
22
use clippy_utils::source::{snippet, snippet_with_context};
33
use clippy_utils::sugg::Sugg;
44
use clippy_utils::{
@@ -114,40 +114,35 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
114114
k: FnKind<'tcx>,
115115
decl: &'tcx FnDecl<'_>,
116116
body: &'tcx Body<'_>,
117-
span: Span,
117+
_: Span,
118118
_: LocalDefId,
119119
) {
120-
if let FnKind::Closure = k {
121-
// Does not apply to closures
122-
return;
123-
}
124-
if in_external_macro(cx.tcx.sess, span) {
125-
return;
126-
}
127-
for arg in iter_input_pats(decl, body) {
128-
// Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
129-
if !is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id) {
130-
return;
131-
}
132-
if let PatKind::Binding(BindingMode(ByRef::Yes(_), _), ..) = arg.pat.kind {
133-
span_lint(
134-
cx,
135-
TOPLEVEL_REF_ARG,
136-
arg.pat.span,
137-
"`ref` directly on a function argument is ignored. \
138-
Consider using a reference type instead",
139-
);
120+
if !matches!(k, FnKind::Closure) {
121+
for arg in iter_input_pats(decl, body) {
122+
if let PatKind::Binding(BindingMode(ByRef::Yes(_), _), ..) = arg.pat.kind
123+
&& is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id)
124+
&& !in_external_macro(cx.tcx.sess, arg.span)
125+
{
126+
span_lint_hir(
127+
cx,
128+
TOPLEVEL_REF_ARG,
129+
arg.hir_id,
130+
arg.pat.span,
131+
"`ref` directly on a function argument is ignored. \
132+
Consider using a reference type instead",
133+
);
134+
}
140135
}
141136
}
142137
}
143138

144139
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
145-
if !in_external_macro(cx.tcx.sess, stmt.span)
146-
&& let StmtKind::Let(local) = stmt.kind
140+
if let StmtKind::Let(local) = stmt.kind
147141
&& let PatKind::Binding(BindingMode(ByRef::Yes(mutabl), _), .., name, None) = local.pat.kind
148142
&& let Some(init) = local.init
149143
// Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
150144
&& is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id)
145+
&& !in_external_macro(cx.tcx.sess, stmt.span)
151146
{
152147
let ctxt = local.span.ctxt();
153148
let mut app = Applicability::MachineApplicable;

clippy_lints/src/mismatching_type_param_order.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,12 @@ declare_lint_pass!(TypeParamMismatch => [MISMATCHING_TYPE_PARAM_ORDER]);
4949

5050
impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch {
5151
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
52-
if !item.span.from_expansion()
53-
&& let ItemKind::Impl(imp) = &item.kind
52+
if let ItemKind::Impl(imp) = &item.kind
5453
&& let TyKind::Path(QPath::Resolved(_, path)) = &imp.self_ty.kind
55-
&& let Some(segment) = path.segments.iter().next()
54+
&& let [segment, ..] = path.segments
5655
&& let Some(generic_args) = segment.args
5756
&& !generic_args.args.is_empty()
57+
&& !item.span.from_expansion()
5858
{
5959
// get the name and span of the generic parameters in the Impl
6060
let mut impl_params = Vec::new();

clippy_lints/src/mut_mut.rs

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -35,33 +35,18 @@ impl<'tcx> LateLintPass<'tcx> for MutMut {
3535
}
3636

3737
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'_>) {
38-
if in_external_macro(cx.sess(), ty.span) {
39-
return;
40-
}
41-
42-
if let hir::TyKind::Ref(
43-
_,
44-
hir::MutTy {
45-
ty: pty,
46-
mutbl: hir::Mutability::Mut,
47-
},
48-
) = ty.kind
38+
if let hir::TyKind::Ref(_, mty) = ty.kind
39+
&& mty.mutbl == hir::Mutability::Mut
40+
&& let hir::TyKind::Ref(_, mty) = mty.ty.kind
41+
&& mty.mutbl == hir::Mutability::Mut
42+
&& !in_external_macro(cx.sess(), ty.span)
4943
{
50-
if let hir::TyKind::Ref(
51-
_,
52-
hir::MutTy {
53-
mutbl: hir::Mutability::Mut,
54-
..
55-
},
56-
) = pty.kind
57-
{
58-
span_lint(
59-
cx,
60-
MUT_MUT,
61-
ty.span,
62-
"generally you want to avoid `&mut &mut _` if possible",
63-
);
64-
}
44+
span_lint(
45+
cx,
46+
MUT_MUT,
47+
ty.span,
48+
"generally you want to avoid `&mut &mut _` if possible",
49+
);
6550
}
6651
}
6752
}

clippy_lints/src/needless_borrowed_ref.rs

Lines changed: 67 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -37,83 +37,75 @@ declare_lint_pass!(NeedlessBorrowedRef => [NEEDLESS_BORROWED_REFERENCE]);
3737

3838
impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
3939
fn check_pat(&mut self, cx: &LateContext<'tcx>, ref_pat: &'tcx Pat<'_>) {
40-
if ref_pat.span.from_expansion() {
41-
// OK, simple enough, lints doesn't check in macro.
42-
return;
43-
}
44-
45-
// Do not lint patterns that are part of an OR `|` pattern, the binding mode must match in all arms
46-
for (_, node) in cx.tcx.hir().parent_iter(ref_pat.hir_id) {
47-
let Node::Pat(pat) = node else { break };
48-
49-
if matches!(pat.kind, PatKind::Or(_)) {
50-
return;
40+
if let PatKind::Ref(pat, Mutability::Not) = ref_pat.kind
41+
&& !ref_pat.span.from_expansion()
42+
&& cx
43+
.tcx
44+
.hir()
45+
.parent_iter(ref_pat.hir_id)
46+
.map_while(|(_, parent)| if let Node::Pat(pat) = parent { Some(pat) } else { None })
47+
// Do not lint patterns that are part of an OR `|` pattern, the binding mode must match in all arms
48+
.all(|pat| !matches!(pat.kind, PatKind::Or(_)))
49+
{
50+
match pat.kind {
51+
// Check sub_pat got a `ref` keyword (excluding `ref mut`).
52+
PatKind::Binding(BindingMode::REF, _, ident, None) => {
53+
span_lint_and_then(
54+
cx,
55+
NEEDLESS_BORROWED_REFERENCE,
56+
ref_pat.span,
57+
"this pattern takes a reference on something that is being dereferenced",
58+
|diag| {
59+
// `&ref ident`
60+
// ^^^^^
61+
let span = ref_pat.span.until(ident.span);
62+
diag.span_suggestion_verbose(
63+
span,
64+
"try removing the `&ref` part",
65+
String::new(),
66+
Applicability::MachineApplicable,
67+
);
68+
},
69+
);
70+
},
71+
// Slices where each element is `ref`: `&[ref a, ref b, ..., ref z]`
72+
PatKind::Slice(
73+
before,
74+
None
75+
| Some(Pat {
76+
kind: PatKind::Wild, ..
77+
}),
78+
after,
79+
) => {
80+
check_subpatterns(
81+
cx,
82+
"dereferencing a slice pattern where every element takes a reference",
83+
ref_pat,
84+
pat,
85+
itertools::chain(before, after),
86+
);
87+
},
88+
PatKind::Tuple(subpatterns, _) | PatKind::TupleStruct(_, subpatterns, _) => {
89+
check_subpatterns(
90+
cx,
91+
"dereferencing a tuple pattern where every element takes a reference",
92+
ref_pat,
93+
pat,
94+
subpatterns,
95+
);
96+
},
97+
PatKind::Struct(_, fields, _) => {
98+
check_subpatterns(
99+
cx,
100+
"dereferencing a struct pattern where every field's pattern takes a reference",
101+
ref_pat,
102+
pat,
103+
fields.iter().map(|field| field.pat),
104+
);
105+
},
106+
_ => {},
51107
}
52108
}
53-
54-
// Only lint immutable refs, because `&mut ref T` may be useful.
55-
let PatKind::Ref(pat, Mutability::Not) = ref_pat.kind else {
56-
return;
57-
};
58-
59-
match pat.kind {
60-
// Check sub_pat got a `ref` keyword (excluding `ref mut`).
61-
PatKind::Binding(BindingMode::REF, _, ident, None) => {
62-
span_lint_and_then(
63-
cx,
64-
NEEDLESS_BORROWED_REFERENCE,
65-
ref_pat.span,
66-
"this pattern takes a reference on something that is being dereferenced",
67-
|diag| {
68-
// `&ref ident`
69-
// ^^^^^
70-
let span = ref_pat.span.until(ident.span);
71-
diag.span_suggestion_verbose(
72-
span,
73-
"try removing the `&ref` part",
74-
String::new(),
75-
Applicability::MachineApplicable,
76-
);
77-
},
78-
);
79-
},
80-
// Slices where each element is `ref`: `&[ref a, ref b, ..., ref z]`
81-
PatKind::Slice(
82-
before,
83-
None
84-
| Some(Pat {
85-
kind: PatKind::Wild, ..
86-
}),
87-
after,
88-
) => {
89-
check_subpatterns(
90-
cx,
91-
"dereferencing a slice pattern where every element takes a reference",
92-
ref_pat,
93-
pat,
94-
itertools::chain(before, after),
95-
);
96-
},
97-
PatKind::Tuple(subpatterns, _) | PatKind::TupleStruct(_, subpatterns, _) => {
98-
check_subpatterns(
99-
cx,
100-
"dereferencing a tuple pattern where every element takes a reference",
101-
ref_pat,
102-
pat,
103-
subpatterns,
104-
);
105-
},
106-
PatKind::Struct(_, fields, _) => {
107-
check_subpatterns(
108-
cx,
109-
"dereferencing a struct pattern where every field's pattern takes a reference",
110-
ref_pat,
111-
pat,
112-
fields.iter().map(|field| field.pat),
113-
);
114-
},
115-
_ => {},
116-
}
117109
}
118110
}
119111

clippy_lints/src/needless_for_each.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor};
33
use rustc_hir::{Block, BlockCheckMode, Closure, Expr, ExprKind, Stmt, StmtKind};
44
use rustc_lint::{LateContext, LateLintPass};
55
use rustc_session::declare_lint_pass;
6-
use rustc_span::{sym, Span, Symbol};
6+
use rustc_span::{sym, Span};
77

88
use clippy_utils::diagnostics::span_lint_and_then;
99
use clippy_utils::is_trait_method;
@@ -55,23 +55,17 @@ declare_lint_pass!(NeedlessForEach => [NEEDLESS_FOR_EACH]);
5555

5656
impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
5757
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
58-
let (StmtKind::Expr(expr) | StmtKind::Semi(expr)) = stmt.kind else {
59-
return;
60-
};
61-
62-
if let ExprKind::MethodCall(method_name, for_each_recv, [for_each_arg], _) = expr.kind
63-
// Check the method name is `for_each`.
64-
&& method_name.ident.name == Symbol::intern("for_each")
65-
// Check `for_each` is an associated function of `Iterator`.
66-
&& is_trait_method(cx, expr, sym::Iterator)
67-
// Checks the receiver of `for_each` is also a method call.
58+
if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind
59+
&& let ExprKind::MethodCall(method_name, for_each_recv, [for_each_arg], _) = expr.kind
6860
&& let ExprKind::MethodCall(_, iter_recv, [], _) = for_each_recv.kind
6961
// Skip the lint if the call chain is too long. e.g. `v.field.iter().for_each()` or
7062
// `v.foo().iter().for_each()` must be skipped.
7163
&& matches!(
7264
iter_recv.kind,
7365
ExprKind::Array(..) | ExprKind::Call(..) | ExprKind::Path(..)
7466
)
67+
&& method_name.ident.name.as_str() == "for_each"
68+
&& is_trait_method(cx, expr, sym::Iterator)
7569
// Checks the type of the `iter` method receiver is NOT a user defined type.
7670
&& has_iter_method(cx, cx.typeck_results().expr_ty(iter_recv)).is_some()
7771
// Skip the lint if the body is not block because this is simpler than `for` loop.

clippy_lints/src/neg_cmp_op_on_partial_ord.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ declare_lint_pass!(NoNegCompOpForPartialOrd => [NEG_CMP_OP_ON_PARTIAL_ORD]);
4545

4646
impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd {
4747
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
48-
if !in_external_macro(cx.sess(), expr.span)
49-
&& let ExprKind::Unary(UnOp::Not, inner) = expr.kind
48+
if let ExprKind::Unary(UnOp::Not, inner) = expr.kind
5049
&& let ExprKind::Binary(ref op, left, _) = inner.kind
5150
&& let BinOpKind::Le | BinOpKind::Ge | BinOpKind::Lt | BinOpKind::Gt = op.node
51+
&& !in_external_macro(cx.sess(), expr.span)
5252
{
5353
let ty = cx.typeck_results().expr_ty(left);
5454

clippy_lints/src/option_env_unwrap.rs

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use clippy_utils::is_direct_expn_of;
33
use rustc_ast::ast::{Expr, ExprKind, MethodCall};
44
use rustc_lint::{EarlyContext, EarlyLintPass};
55
use rustc_session::declare_lint_pass;
6-
use rustc_span::{sym, Span};
6+
use rustc_span::sym;
77

88
declare_clippy_lint! {
99
/// ### What it does
@@ -35,30 +35,18 @@ declare_lint_pass!(OptionEnvUnwrap => [OPTION_ENV_UNWRAP]);
3535

3636
impl EarlyLintPass for OptionEnvUnwrap {
3737
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
38-
fn lint(cx: &EarlyContext<'_>, span: Span) {
38+
if let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &expr.kind
39+
&& matches!(seg.ident.name, sym::expect | sym::unwrap)
40+
&& is_direct_expn_of(receiver.span, "option_env").is_some()
41+
{
3942
span_lint_and_help(
4043
cx,
4144
OPTION_ENV_UNWRAP,
42-
span,
45+
expr.span,
4346
"this will panic at run-time if the environment variable doesn't exist at compile-time",
4447
None,
4548
"consider using the `env!` macro instead",
4649
);
4750
}
48-
49-
if let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &expr.kind
50-
&& matches!(seg.ident.name, sym::expect | sym::unwrap)
51-
{
52-
if let ExprKind::Call(caller, _) = &receiver.kind &&
53-
// If it exists, it will be ::core::option::Option::Some("<env var>").unwrap() (A method call in the HIR)
54-
is_direct_expn_of(caller.span, "option_env").is_some()
55-
{
56-
lint(cx, expr.span);
57-
} else if let ExprKind::Path(_, caller) = &receiver.kind && // If it doesn't exist, it will be ::core::option::Option::None::<&'static str>.unwrap() (A path in the HIR)
58-
is_direct_expn_of(caller.span, "option_env").is_some()
59-
{
60-
lint(cx, expr.span);
61-
}
62-
}
6351
}
6452
}

clippy_lints/src/permissions_set_readonly_false.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ declare_lint_pass!(PermissionsSetReadonlyFalse => [PERMISSIONS_SET_READONLY_FALS
3131
impl<'tcx> LateLintPass<'tcx> for PermissionsSetReadonlyFalse {
3232
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
3333
if let ExprKind::MethodCall(path, receiver, [arg], _) = &expr.kind
34-
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::FsPermissions)
35-
&& path.ident.name == sym!(set_readonly)
3634
&& let ExprKind::Lit(lit) = &arg.kind
3735
&& LitKind::Bool(false) == lit.node
36+
&& path.ident.name.as_str() == "set_readonly"
37+
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::FsPermissions)
3838
{
3939
span_lint_and_then(
4040
cx,

0 commit comments

Comments
 (0)