Skip to content

Commit 3813a7b

Browse files
committed
Auto merge of #11538 - Jarcho:proc_mac, r=dswij
Fix `is_from_proc_macro` patterns fixes #11533 changelog: none
2 parents 252103b + f3f2f17 commit 3813a7b

12 files changed

+144
-67
lines changed

clippy_lints/src/as_conversions.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,10 @@ declare_lint_pass!(AsConversions => [AS_CONVERSIONS]);
4848

4949
impl<'tcx> LateLintPass<'tcx> for AsConversions {
5050
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
51-
if in_external_macro(cx.sess(), expr.span) || is_from_proc_macro(cx, expr) {
52-
return;
53-
}
54-
55-
if let ExprKind::Cast(_, _) = expr.kind {
51+
if let ExprKind::Cast(_, _) = expr.kind
52+
&& !in_external_macro(cx.sess(), expr.span)
53+
&& !is_from_proc_macro(cx, expr)
54+
{
5655
span_lint_and_help(
5756
cx,
5857
AS_CONVERSIONS,

clippy_lints/src/borrow_deref_ref.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
5757
&& !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..))
5858
&& let ref_ty = cx.typeck_results().expr_ty(deref_target)
5959
&& let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind()
60-
&& !is_from_proc_macro(cx, e)
6160
{
6261
if let Some(parent_expr) = get_parent_expr(cx, e) {
6362
if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..))
@@ -75,6 +74,9 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
7574
return;
7675
}
7776
}
77+
if is_from_proc_macro(cx, e) {
78+
return;
79+
}
7880

7981
span_lint_and_then(
8082
cx,

clippy_lints/src/manual_float_methods.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,16 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
105105
// case somebody does that for some reason
106106
&& (is_infinity(const_1) && is_neg_infinity(const_2)
107107
|| is_neg_infinity(const_1) && is_infinity(const_2))
108-
&& !is_from_proc_macro(cx, expr)
109108
&& let Some(local_snippet) = snippet_opt(cx, first.span)
110109
{
111110
let variant = match (kind.node, lhs_kind.node, rhs_kind.node) {
112111
(BinOpKind::Or, BinOpKind::Eq, BinOpKind::Eq) => Variant::ManualIsInfinite,
113112
(BinOpKind::And, BinOpKind::Ne, BinOpKind::Ne) => Variant::ManualIsFinite,
114113
_ => return,
115114
};
115+
if is_from_proc_macro(cx, expr) {
116+
return;
117+
}
116118

117119
span_lint_and_then(cx, variant.lint(), expr.span, variant.msg(), |diag| {
118120
match variant {

clippy_lints/src/methods/unnecessary_lazy_eval.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@ pub(super) fn check<'tcx>(
1919
arg: &'tcx hir::Expr<'_>,
2020
simplify_using: &str,
2121
) {
22-
if is_from_proc_macro(cx, expr) {
23-
return;
24-
}
25-
2622
let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option);
2723
let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
2824
let is_bool = cx.typeck_results().expr_ty(recv).is_bool();
@@ -32,7 +28,7 @@ pub(super) fn check<'tcx>(
3228
let body = cx.tcx.hir().body(body);
3329
let body_expr = &body.value;
3430

35-
if usage::BindingUsageFinder::are_params_used(cx, body) {
31+
if usage::BindingUsageFinder::are_params_used(cx, body) || is_from_proc_macro(cx, expr) {
3632
return;
3733
}
3834

clippy_lints/src/needless_if.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ impl LateLintPass<'_> for NeedlessIf {
4444
&& block.stmts.is_empty()
4545
&& block.expr.is_none()
4646
&& !in_external_macro(cx.sess(), expr.span)
47-
&& !is_from_proc_macro(cx, expr)
4847
&& let Some(then_snippet) = snippet_opt(cx, then.span)
4948
// Ignore
5049
// - empty macro expansions
@@ -53,6 +52,7 @@ impl LateLintPass<'_> for NeedlessIf {
5352
// - #[cfg]'d out code
5453
&& then_snippet.chars().all(|ch| matches!(ch, '{' | '}') || ch.is_ascii_whitespace())
5554
&& let Some(cond_snippet) = snippet_opt(cx, cond.span)
55+
&& !is_from_proc_macro(cx, expr)
5656
{
5757
span_lint_and_sugg(
5858
cx,

clippy_lints/src/operators/arithmetic_side_effects.rs

+14-11
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,11 @@ impl ArithmeticSideEffects {
132132
}
133133

134134
// Common entry-point to avoid code duplication.
135-
fn issue_lint(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
135+
fn issue_lint<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
136+
if is_from_proc_macro(cx, expr) {
137+
return;
138+
}
139+
136140
let msg = "arithmetic operation that can potentially result in unexpected side-effects";
137141
span_lint(cx, ARITHMETIC_SIDE_EFFECTS, expr.span, msg);
138142
self.expr_span = Some(expr.span);
@@ -160,10 +164,10 @@ impl ArithmeticSideEffects {
160164
fn manage_bin_ops<'tcx>(
161165
&mut self,
162166
cx: &LateContext<'tcx>,
163-
expr: &hir::Expr<'tcx>,
167+
expr: &'tcx hir::Expr<'_>,
164168
op: &Spanned<hir::BinOpKind>,
165-
lhs: &hir::Expr<'tcx>,
166-
rhs: &hir::Expr<'tcx>,
169+
lhs: &'tcx hir::Expr<'_>,
170+
rhs: &'tcx hir::Expr<'_>,
167171
) {
168172
if constant_simple(cx, cx.typeck_results(), expr).is_some() {
169173
return;
@@ -236,10 +240,10 @@ impl ArithmeticSideEffects {
236240
/// provided input.
237241
fn manage_method_call<'tcx>(
238242
&mut self,
239-
args: &[hir::Expr<'tcx>],
243+
args: &'tcx [hir::Expr<'_>],
240244
cx: &LateContext<'tcx>,
241-
ps: &hir::PathSegment<'tcx>,
242-
receiver: &hir::Expr<'tcx>,
245+
ps: &'tcx hir::PathSegment<'_>,
246+
receiver: &'tcx hir::Expr<'_>,
243247
) {
244248
let Some(arg) = args.first() else {
245249
return;
@@ -264,8 +268,8 @@ impl ArithmeticSideEffects {
264268
fn manage_unary_ops<'tcx>(
265269
&mut self,
266270
cx: &LateContext<'tcx>,
267-
expr: &hir::Expr<'tcx>,
268-
un_expr: &hir::Expr<'tcx>,
271+
expr: &'tcx hir::Expr<'_>,
272+
un_expr: &'tcx hir::Expr<'_>,
269273
un_op: hir::UnOp,
270274
) {
271275
let hir::UnOp::Neg = un_op else {
@@ -287,14 +291,13 @@ impl ArithmeticSideEffects {
287291

288292
fn should_skip_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) -> bool {
289293
is_lint_allowed(cx, ARITHMETIC_SIDE_EFFECTS, expr.hir_id)
290-
|| is_from_proc_macro(cx, expr)
291294
|| self.expr_span.is_some()
292295
|| self.const_span.map_or(false, |sp| sp.contains(expr.span))
293296
}
294297
}
295298

296299
impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
297-
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) {
300+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
298301
if self.should_skip_expr(cx, expr) {
299302
return;
300303
}

clippy_lints/src/single_call_fn.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ impl<'tcx> LateLintPass<'tcx> for SingleCallFn {
7272
) {
7373
if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id)
7474
|| in_external_macro(cx.sess(), span)
75-
|| is_from_proc_macro(cx, &(&kind, body, cx.tcx.local_def_id_to_hir_id(def_id), span))
7675
|| is_in_test_function(cx.tcx, body.value.hir_id)
76+
|| is_from_proc_macro(cx, &(&kind, body, cx.tcx.local_def_id_to_hir_id(def_id), span))
7777
{
7878
return;
7979
}

clippy_utils/src/check_proc_macro.rs

+41-39
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
//! code was written, and check if the span contains that text. Note this will only work correctly
1313
//! if the span is not from a `macro_rules` based macro.
1414
15-
use rustc_ast::ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, UintTy};
15+
use rustc_ast::ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, TraitObjectSyntax, UintTy};
1616
use rustc_ast::token::CommentKind;
1717
use rustc_ast::AttrStyle;
1818
use rustc_hir::intravisit::FnKind;
1919
use rustc_hir::{
20-
Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, HirId, Impl, ImplItem,
21-
ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, MutTy, Node, QPath, TraitItem, TraitItemKind, Ty,
22-
TyKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource,
20+
Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl,
21+
ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, MutTy, Node, QPath, TraitItem,
22+
TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource,
2323
};
2424
use rustc_lint::{LateContext, LintContext};
2525
use rustc_middle::ty::TyCtxt;
@@ -33,8 +33,6 @@ use rustc_target::spec::abi::Abi;
3333
pub enum Pat {
3434
/// A single string.
3535
Str(&'static str),
36-
/// A single string.
37-
OwnedStr(String),
3836
/// Any of the given strings.
3937
MultiStr(&'static [&'static str]),
4038
/// Any of the given strings.
@@ -59,14 +57,12 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) ->
5957
let end_str = s.trim_end_matches(|c: char| c.is_whitespace() || c == ')' || c == ',');
6058
(match start_pat {
6159
Pat::Str(text) => start_str.starts_with(text),
62-
Pat::OwnedStr(text) => start_str.starts_with(&text),
6360
Pat::MultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)),
6461
Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)),
6562
Pat::Sym(sym) => start_str.starts_with(sym.as_str()),
6663
Pat::Num => start_str.as_bytes().first().map_or(false, u8::is_ascii_digit),
6764
} && match end_pat {
6865
Pat::Str(text) => end_str.ends_with(text),
69-
Pat::OwnedStr(text) => end_str.starts_with(&text),
7066
Pat::MultiStr(texts) => texts.iter().any(|s| start_str.ends_with(s)),
7167
Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)),
7268
Pat::Sym(sym) => end_str.ends_with(sym.as_str()),
@@ -125,6 +121,8 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) {
125121
fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) {
126122
match e.kind {
127123
ExprKind::ConstBlock(_) => (Pat::Str("const"), Pat::Str("}")),
124+
// Parenthesis are trimmed from the text before the search patterns are matched.
125+
// See: `span_matches_pat`
128126
ExprKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")),
129127
ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat(tcx, e).1),
130128
ExprKind::Unary(UnOp::Not, e) => (Pat::Str("!"), expr_search_pat(tcx, e).1),
@@ -286,23 +284,17 @@ fn fn_kind_pat(tcx: TyCtxt<'_>, kind: &FnKind<'_>, body: &Body<'_>, hir_id: HirI
286284
fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) {
287285
match attr.kind {
288286
AttrKind::Normal(..) => {
289-
let mut pat = if matches!(attr.style, AttrStyle::Outer) {
290-
(Pat::Str("#["), Pat::Str("]"))
291-
} else {
292-
(Pat::Str("#!["), Pat::Str("]"))
293-
};
294-
295-
if let Some(ident) = attr.ident()
296-
&& let Pat::Str(old_pat) = pat.0
297-
{
287+
if let Some(ident) = attr.ident() {
298288
// TODO: I feel like it's likely we can use `Cow` instead but this will require quite a bit of
299289
// refactoring
300290
// NOTE: This will likely have false positives, like `allow = 1`
301-
pat.0 = Pat::OwnedMultiStr(vec![ident.to_string(), old_pat.to_owned()]);
302-
pat.1 = Pat::Str("");
291+
(
292+
Pat::OwnedMultiStr(vec![ident.to_string(), "#".to_owned()]),
293+
Pat::Str(""),
294+
)
295+
} else {
296+
(Pat::Str("#"), Pat::Str("]"))
303297
}
304-
305-
pat
306298
},
307299
AttrKind::DocComment(_kind @ CommentKind::Line, ..) => {
308300
if matches!(attr.style, AttrStyle::Outer) {
@@ -324,32 +316,42 @@ fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) {
324316
fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) {
325317
match ty.kind {
326318
TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")),
327-
TyKind::Ptr(MutTy { mutbl, ty }) => (
328-
if mutbl.is_mut() {
329-
Pat::Str("*const")
330-
} else {
331-
Pat::Str("*mut")
332-
},
333-
ty_search_pat(ty).1,
334-
),
319+
TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ty_search_pat(ty).1),
335320
TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1),
336321
TyKind::BareFn(bare_fn) => (
337-
Pat::OwnedStr(format!("{}{} fn", bare_fn.unsafety.prefix_str(), bare_fn.abi.name())),
338-
ty_search_pat(ty).1,
322+
if bare_fn.unsafety == Unsafety::Unsafe {
323+
Pat::Str("unsafe")
324+
} else if bare_fn.abi != Abi::Rust {
325+
Pat::Str("extern")
326+
} else {
327+
Pat::MultiStr(&["fn", "extern"])
328+
},
329+
match bare_fn.decl.output {
330+
FnRetTy::DefaultReturn(_) => {
331+
if let [.., ty] = bare_fn.decl.inputs {
332+
ty_search_pat(ty).1
333+
} else {
334+
Pat::Str("(")
335+
}
336+
},
337+
FnRetTy::Return(ty) => ty_search_pat(ty).1,
338+
},
339339
),
340-
TyKind::Never => (Pat::Str("!"), Pat::Str("")),
341-
TyKind::Tup(..) => (Pat::Str("("), Pat::Str(")")),
340+
TyKind::Never => (Pat::Str("!"), Pat::Str("!")),
341+
// Parenthesis are trimmed from the text before the search patterns are matched.
342+
// See: `span_matches_pat`
343+
TyKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")),
344+
TyKind::Tup([ty]) => ty_search_pat(ty),
345+
TyKind::Tup([head, .., tail]) => (ty_search_pat(head).0, ty_search_pat(tail).1),
342346
TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")),
343347
TyKind::Path(qpath) => qpath_search_pat(&qpath),
344-
// NOTE: This is missing `TraitObject`. It will always return true then.
348+
TyKind::Infer => (Pat::Str("_"), Pat::Str("_")),
349+
TyKind::TraitObject(_, _, TraitObjectSyntax::Dyn) => (Pat::Str("dyn"), Pat::Str("")),
350+
// NOTE: `TraitObject` is incomplete. It will always return true then.
345351
_ => (Pat::Str(""), Pat::Str("")),
346352
}
347353
}
348354

349-
fn ident_search_pat(ident: Ident) -> (Pat, Pat) {
350-
(Pat::OwnedStr(ident.name.as_str().to_owned()), Pat::Str(""))
351-
}
352-
353355
pub trait WithSearchPat<'cx> {
354356
type Context: LintContext;
355357
fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat);
@@ -408,7 +410,7 @@ impl<'cx> WithSearchPat<'cx> for Ident {
408410
type Context = LateContext<'cx>;
409411

410412
fn search_pat(&self, _cx: &Self::Context) -> (Pat, Pat) {
411-
ident_search_pat(*self)
413+
(Pat::Sym(self.name), Pat::Sym(self.name))
412414
}
413415

414416
fn span(&self) -> Span {

tests/ui/doc_unsafe.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@aux-build:proc_macros.rs
22

3-
#![allow(clippy::let_unit_value)]
3+
#![allow(clippy::let_unit_value, clippy::needless_pass_by_ref_mut)]
44

55
extern crate proc_macros;
66
use proc_macros::external;

tests/ui/needless_pass_by_ref_mut.rs

+13
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,19 @@ fn filter_copy<T: Copy>(predicate: &mut impl FnMut(T) -> bool) -> impl FnMut(&T)
307307
move |&item| predicate(item)
308308
}
309309

310+
// `is_from_proc_macro` stress tests
311+
fn _empty_tup(x: &mut (())) {}
312+
fn _single_tup(x: &mut ((i32,))) {}
313+
fn _multi_tup(x: &mut ((i32, u32))) {}
314+
fn _fn(x: &mut (fn())) {}
315+
#[rustfmt::skip]
316+
fn _extern_rust_fn(x: &mut extern "Rust" fn()) {}
317+
fn _extern_c_fn(x: &mut extern "C" fn()) {}
318+
fn _unsafe_fn(x: &mut unsafe fn()) {}
319+
fn _unsafe_extern_fn(x: &mut unsafe extern "C" fn()) {}
320+
fn _fn_with_arg(x: &mut unsafe extern "C" fn(i32)) {}
321+
fn _fn_with_ret(x: &mut unsafe extern "C" fn() -> (i32)) {}
322+
310323
fn main() {
311324
let mut u = 0;
312325
let mut v = vec![0];

0 commit comments

Comments
 (0)