From cd2d2a034d4e88ac6a3635c6a0cf2079eedecc21 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 6 Aug 2025 23:03:55 +0200 Subject: [PATCH 01/16] init by copying `ty_search_pat` --- clippy_utils/src/check_proc_macro.rs | 42 ++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index c4a759e919b1..d569865553aa 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -13,6 +13,7 @@ //! if the span is not from a `macro_rules` based macro. use rustc_abi::ExternAbi; +use rustc_ast as ast; use rustc_ast::AttrStyle; use rustc_ast::ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, TraitObjectSyntax, UintTy}; use rustc_ast::token::CommentKind; @@ -411,6 +412,47 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { } } +fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { + match ty.kind { + TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), + TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ty_search_pat(ty).1), + TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1), + TyKind::FnPtr(fn_ptr) => ( + if fn_ptr.safety.is_unsafe() { + Pat::Str("unsafe") + } else if fn_ptr.abi != ExternAbi::Rust { + Pat::Str("extern") + } else { + Pat::MultiStr(&["fn", "extern"]) + }, + match fn_ptr.decl.output { + FnRetTy::DefaultReturn(_) => { + if let [.., ty] = fn_ptr.decl.inputs { + ty_search_pat(ty).1 + } else { + Pat::Str("(") + } + }, + FnRetTy::Return(ty) => ty_search_pat(ty).1, + }, + ), + TyKind::Never => (Pat::Str("!"), Pat::Str("!")), + // Parenthesis are trimmed from the text before the search patterns are matched. + // See: `span_matches_pat` + TyKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")), + TyKind::Tup([ty]) => ty_search_pat(ty), + TyKind::Tup([head, .., tail]) => (ty_search_pat(head).0, ty_search_pat(tail).1), + TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")), + TyKind::Path(qpath) => qpath_search_pat(&qpath), + TyKind::Infer(()) => (Pat::Str("_"), Pat::Str("_")), + TyKind::TraitObject(_, tagged_ptr) if let TraitObjectSyntax::Dyn = tagged_ptr.tag() => { + (Pat::Str("dyn"), Pat::Str("")) + }, + // NOTE: `TraitObject` is incomplete. It will always return true then. + _ => (Pat::Str(""), Pat::Str("")), + } +} + fn ident_search_pat(ident: Ident) -> (Pat, Pat) { (Pat::Sym(ident.name), Pat::Sym(ident.name)) } From a4dbbc9bf1cea10b396eec28e052a5096dc7da29 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 6 Aug 2025 23:04:49 +0200 Subject: [PATCH 02/16] rename recursive function call --- clippy_utils/src/check_proc_macro.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index d569865553aa..1ea68c1c2212 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -413,10 +413,12 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { } fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { - match ty.kind { + use ast::{FnRetTy, MutTy, TyKind}; + + match &ty.kind { TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), - TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ty_search_pat(ty).1), - TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1), + TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ast_ty_search_pat(ty).1), + TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ast_ty_search_pat(ty).1), TyKind::FnPtr(fn_ptr) => ( if fn_ptr.safety.is_unsafe() { Pat::Str("unsafe") @@ -428,20 +430,20 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { match fn_ptr.decl.output { FnRetTy::DefaultReturn(_) => { if let [.., ty] = fn_ptr.decl.inputs { - ty_search_pat(ty).1 + ast_ty_search_pat(ty).1 } else { Pat::Str("(") } }, - FnRetTy::Return(ty) => ty_search_pat(ty).1, + FnRetTy::Return(ty) => ast_ty_search_pat(ty).1, }, ), TyKind::Never => (Pat::Str("!"), Pat::Str("!")), // Parenthesis are trimmed from the text before the search patterns are matched. // See: `span_matches_pat` TyKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")), - TyKind::Tup([ty]) => ty_search_pat(ty), - TyKind::Tup([head, .., tail]) => (ty_search_pat(head).0, ty_search_pat(tail).1), + TyKind::Tup([ty]) => ast_ty_search_pat(ty), + TyKind::Tup([head, .., tail]) => (ast_ty_search_pat(head).0, ast_ty_search_pat(tail).1), TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")), TyKind::Path(qpath) => qpath_search_pat(&qpath), TyKind::Infer(()) => (Pat::Str("_"), Pat::Str("_")), From 2de81f56ec835d45858d0b2d80e8f1d7e1f1d1e3 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 6 Aug 2025 23:06:06 +0200 Subject: [PATCH 03/16] Infer is a unit variant --- clippy_utils/src/check_proc_macro.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 1ea68c1c2212..792c546e8ffc 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -446,7 +446,7 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { TyKind::Tup([head, .., tail]) => (ast_ty_search_pat(head).0, ast_ty_search_pat(tail).1), TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")), TyKind::Path(qpath) => qpath_search_pat(&qpath), - TyKind::Infer(()) => (Pat::Str("_"), Pat::Str("_")), + TyKind::Infer => (Pat::Str("_"), Pat::Str("_")), TyKind::TraitObject(_, tagged_ptr) if let TraitObjectSyntax::Dyn = tagged_ptr.tag() => { (Pat::Str("dyn"), Pat::Str("")) }, From 73d04ba29f2db9073cc37bb43e9d0faf921344b2 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 6 Aug 2025 23:06:19 +0200 Subject: [PATCH 04/16] fix Path --- clippy_utils/src/check_proc_macro.rs | 51 ++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 792c546e8ffc..d0a769e96b72 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -15,7 +15,9 @@ use rustc_abi::ExternAbi; use rustc_ast as ast; use rustc_ast::AttrStyle; -use rustc_ast::ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, TraitObjectSyntax, UintTy}; +use rustc_ast::ast::{ + AttrKind, Attribute, GenericArgs, IntTy, LitIntType, LitKind, StrStyle, TraitObjectSyntax, UintTy, +}; use rustc_ast::token::CommentKind; use rustc_hir::intravisit::FnKind; use rustc_hir::{ @@ -445,7 +447,52 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { TyKind::Tup([ty]) => ast_ty_search_pat(ty), TyKind::Tup([head, .., tail]) => (ast_ty_search_pat(head).0, ast_ty_search_pat(tail).1), TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")), - TyKind::Path(qpath) => qpath_search_pat(&qpath), + TyKind::Path(qself_path, path) => { + let start = if qself_path.is_some() { + Pat::Str("<") + } else if let Some(first) = path.segments.first() { + ident_search_pat(first.ident).0 + } else { + // this shouldn't be possible, but sure + Pat::Str("") + }; + let end = if let Some(last) = path.segments.last() { + match last.args.as_deref() { + // last `>` in `std::foo::Bar` + Some(GenericArgs::AngleBracketed(_)) => Pat::Str(">"), + Some(GenericArgs::Parenthesized(par_args)) => match &par_args.output { + FnRetTy::Default(_) => { + if let Some(last) = par_args.inputs.last() { + // `B` in `(A, B)` -- `)` gets stripped + ast_ty_search_pat(last).1 + } else { + // `(` in `()` -- `)` gets stripped + Pat::Str("(") + } + }, + // `C` in `(A, B) -> C` + FnRetTy::Ty(ty) => ast_ty_search_pat(ty).1, + }, + // last `..` in `(..)` -- `)` gets stripped + Some(GenericArgs::ParenthesizedElided(_)) => Pat::Str(".."), + // `bar` in `std::foo::bar` + None => ident_search_pat(last.ident).1, + } + } else { + // this shouldn't be possible, but sure + #[allow( + clippy::collapsible_else_if, + reason = "we want to keep these cases together, since they are both impossible" + )] + if qself_path.is_some() { + // last `>` in `` + Pat::Str(">") + } else { + Pat::Str("") + } + }; + (start, end) + }, TyKind::Infer => (Pat::Str("_"), Pat::Str("_")), TyKind::TraitObject(_, tagged_ptr) if let TraitObjectSyntax::Dyn = tagged_ptr.tag() => { (Pat::Str("dyn"), Pat::Str("")) From baf09e2fa2d6ea3a45b4b03ddbd10566c13f3c4b Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 6 Aug 2025 23:07:19 +0200 Subject: [PATCH 05/16] OpaqueDef is called ImplTrait --- clippy_utils/src/check_proc_macro.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index d0a769e96b72..a57c7c60cdae 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -446,7 +446,7 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { TyKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")), TyKind::Tup([ty]) => ast_ty_search_pat(ty), TyKind::Tup([head, .., tail]) => (ast_ty_search_pat(head).0, ast_ty_search_pat(tail).1), - TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")), + TyKind::ImplTrait(..) => (Pat::Str("impl"), Pat::Str("")), TyKind::Path(qself_path, path) => { let start = if qself_path.is_some() { Pat::Str("<") From f5292331c3f6c631b0c5544f8c4401c50d032fb7 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 6 Aug 2025 23:09:26 +0200 Subject: [PATCH 06/16] fix Tup --- clippy_utils/src/check_proc_macro.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index a57c7c60cdae..c34d6c72f4ca 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -443,9 +443,11 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { TyKind::Never => (Pat::Str("!"), Pat::Str("!")), // Parenthesis are trimmed from the text before the search patterns are matched. // See: `span_matches_pat` - TyKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")), - TyKind::Tup([ty]) => ast_ty_search_pat(ty), - TyKind::Tup([head, .., tail]) => (ast_ty_search_pat(head).0, ast_ty_search_pat(tail).1), + TyKind::Tup(tup) => match &**tup { + [] => (Pat::Str(")"), Pat::Str("(")), + [ty] => ast_ty_search_pat(ty), + [head, .., tail] => (ast_ty_search_pat(head).0, ast_ty_search_pat(tail).1), + }, TyKind::ImplTrait(..) => (Pat::Str("impl"), Pat::Str("")), TyKind::Path(qself_path, path) => { let start = if qself_path.is_some() { From c7b75880dc541b298918928a55e56aec2359f4a5 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 6 Aug 2025 23:09:38 +0200 Subject: [PATCH 07/16] fix TraitObject --- clippy_utils/src/check_proc_macro.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index c34d6c72f4ca..2de131f05c26 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -415,7 +415,7 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { } fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { - use ast::{FnRetTy, MutTy, TyKind}; + use ast::{FnRetTy, MutTy, TraitObjectSyntax, TyKind}; match &ty.kind { TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), @@ -496,10 +496,14 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { (start, end) }, TyKind::Infer => (Pat::Str("_"), Pat::Str("_")), - TyKind::TraitObject(_, tagged_ptr) if let TraitObjectSyntax::Dyn = tagged_ptr.tag() => { - (Pat::Str("dyn"), Pat::Str("")) + TyKind::TraitObject(_, trait_obj_syntax) => { + if let TraitObjectSyntax::Dyn = trait_obj_syntax { + (Pat::Str("dyn"), Pat::Str("")) + } else { + // NOTE: `TraitObject` is incomplete. It will always return true then. + (Pat::Str(""), Pat::Str("")) + } }, - // NOTE: `TraitObject` is incomplete. It will always return true then. _ => (Pat::Str(""), Pat::Str("")), } } From 742cba339a572a77809dd15bda0714e46b1e64ca Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 7 Aug 2025 00:21:06 +0200 Subject: [PATCH 08/16] fix FnPtr --- clippy_utils/src/check_proc_macro.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 2de131f05c26..00583d6766e0 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -29,7 +29,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::symbol::{Ident, kw}; -use rustc_span::{Span, Symbol}; +use rustc_span::{Span, Symbol, sym}; /// The search pattern to look for. Used by `span_matches_pat` #[derive(Clone)] @@ -415,29 +415,31 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { } fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { - use ast::{FnRetTy, MutTy, TraitObjectSyntax, TyKind}; + use ast::{Extern, FnRetTy, MutTy, Safety, TraitObjectSyntax, TyKind}; match &ty.kind { TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ast_ty_search_pat(ty).1), TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ast_ty_search_pat(ty).1), TyKind::FnPtr(fn_ptr) => ( - if fn_ptr.safety.is_unsafe() { + if let Safety::Unsafe(_) = fn_ptr.safety { Pat::Str("unsafe") - } else if fn_ptr.abi != ExternAbi::Rust { - Pat::Str("extern") - } else { + } else if let Extern::Explicit(strlit, _) = fn_ptr.ext + && strlit.symbol == sym::rust + { Pat::MultiStr(&["fn", "extern"]) + } else { + Pat::Str("extern") }, - match fn_ptr.decl.output { - FnRetTy::DefaultReturn(_) => { - if let [.., ty] = fn_ptr.decl.inputs { - ast_ty_search_pat(ty).1 + match &fn_ptr.decl.output { + FnRetTy::Default(_) => { + if let [.., param] = &*fn_ptr.decl.inputs { + ast_ty_search_pat(¶m.ty).1 } else { Pat::Str("(") } }, - FnRetTy::Return(ty) => ast_ty_search_pat(ty).1, + FnRetTy::Ty(ty) => ast_ty_search_pat(ty).1, }, ), TyKind::Never => (Pat::Str("!"), Pat::Str("!")), From 41614fcc88d3e11d61f94172537b9c9840a2a970 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 7 Aug 2025 00:29:36 +0200 Subject: [PATCH 09/16] add Paren --- clippy_utils/src/check_proc_macro.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 00583d6766e0..10f7fe649436 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -498,6 +498,7 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { (start, end) }, TyKind::Infer => (Pat::Str("_"), Pat::Str("_")), + TyKind::Paren(ty) => ast_ty_search_pat(ty), TyKind::TraitObject(_, trait_obj_syntax) => { if let TraitObjectSyntax::Dyn = trait_obj_syntax { (Pat::Str("dyn"), Pat::Str("")) From 2bd9f98928e051dbb6e065c64410599de6e7f93c Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 7 Aug 2025 00:34:50 +0200 Subject: [PATCH 10/16] add UnsafeBinder to the existing function as well --- clippy_utils/src/check_proc_macro.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 10f7fe649436..f82c643151e8 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -406,6 +406,7 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")), TyKind::Path(qpath) => qpath_search_pat(&qpath), TyKind::Infer(()) => (Pat::Str("_"), Pat::Str("_")), + TyKind::UnsafeBinder(binder_ty) => (Pat::Str("unsafe"), ty_search_pat(binder_ty.inner_ty).1), TyKind::TraitObject(_, tagged_ptr) if let TraitObjectSyntax::Dyn = tagged_ptr.tag() => { (Pat::Str("dyn"), Pat::Str("")) }, @@ -499,6 +500,7 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { }, TyKind::Infer => (Pat::Str("_"), Pat::Str("_")), TyKind::Paren(ty) => ast_ty_search_pat(ty), + TyKind::UnsafeBinder(binder_ty) => (Pat::Str("unsafe"), ast_ty_search_pat(&binder_ty.inner_ty).1), TyKind::TraitObject(_, trait_obj_syntax) => { if let TraitObjectSyntax::Dyn = trait_obj_syntax { (Pat::Str("dyn"), Pat::Str("")) From 0512002f12f3321526237e9026fafd56c2c99a3a Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 11 Aug 2025 15:21:04 +0200 Subject: [PATCH 11/16] add PinnedRef --- clippy_utils/src/check_proc_macro.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index f82c643151e8..ac4164943b40 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -421,7 +421,9 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { match &ty.kind { TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ast_ty_search_pat(ty).1), - TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ast_ty_search_pat(ty).1), + TyKind::Ref(_, MutTy { ty, .. }) | TyKind::PinnedRef(_, MutTy { ty, .. }) => { + (Pat::Str("&"), ast_ty_search_pat(ty).1) + }, TyKind::FnPtr(fn_ptr) => ( if let Safety::Unsafe(_) = fn_ptr.safety { Pat::Str("unsafe") From bbd0d46e1995354517f15baafccc84269e9f5476 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 11 Aug 2025 15:35:09 +0200 Subject: [PATCH 12/16] add MacCall --- clippy_utils/src/check_proc_macro.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index ac4164943b40..d4335689c1ea 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -511,6 +511,14 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { (Pat::Str(""), Pat::Str("")) } }, + TyKind::MacCall(mac_call) => { + let start = if let Some(first) = mac_call.path.segments.first() { + ident_search_pat(first.ident).0 + } else { + Pat::Str("") + }; + (start, Pat::Str("")) + }, _ => (Pat::Str(""), Pat::Str("")), } } From 17c0cabf988a0a68808b5e78d9c3bd0c2ed3d1cb Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 12 Aug 2025 15:54:39 +0200 Subject: [PATCH 13/16] add ImplicitSelf --- clippy_utils/src/check_proc_macro.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index d4335689c1ea..2f1d380be566 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -519,7 +519,9 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { }; (start, Pat::Str("")) }, - _ => (Pat::Str(""), Pat::Str("")), + + // implicit, so has no contents to match against + TyKind::ImplicitSelf | _ => (Pat::Str(""), Pat::Str("")), } } From 457e0208dfbe916ed441586943195c294cd14162 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 12 Aug 2025 15:55:20 +0200 Subject: [PATCH 14/16] add misc kinds: Pat, CVarArgs, Typeof, Dummy, Err --- clippy_utils/src/check_proc_macro.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 2f1d380be566..649460dd8750 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -521,7 +521,18 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { }, // implicit, so has no contents to match against - TyKind::ImplicitSelf | _ => (Pat::Str(""), Pat::Str("")), + TyKind::ImplicitSelf + + // experimental + |TyKind::Pat(..) + + // unused + | TyKind::CVarArgs + | TyKind::Typeof(_) + + // placeholder + | TyKind::Dummy + | TyKind::Err(_) => (Pat::Str(""), Pat::Str("")), } } From 217fc30fb65bdbdc46f17ab1eee9bbd6d9286d21 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 11 Aug 2025 16:04:45 +0200 Subject: [PATCH 15/16] (finally) implement `WithSearchPat` --- clippy_utils/src/check_proc_macro.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 649460dd8750..47f9d0591e92 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -570,6 +570,7 @@ fn span(&self) -> Span { impl_with_search_pat!((_cx: LateContext<'tcx>, self: Path<'_>) => path_search_pat(self)); impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: Attribute) => attr_search_pat(self)); +impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: ast::Ty) => ast_ty_search_pat(self)); impl<'cx> WithSearchPat<'cx> for (&FnKind<'cx>, &Body<'cx>, HirId, Span) { type Context = LateContext<'cx>; From 2459ad66a48d2d693f4f30a599c28bfc36603333 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 7 Aug 2025 00:38:50 +0200 Subject: [PATCH 16/16] make the lint early-pass --- clippy_lints/src/let_with_type_underscore.rs | 16 ++++++++-------- clippy_lints/src/lib.rs | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/let_with_type_underscore.rs b/clippy_lints/src/let_with_type_underscore.rs index 5b0f95ffc377..24a4c321bdab 100644 --- a/clippy_lints/src/let_with_type_underscore.rs +++ b/clippy_lints/src/let_with_type_underscore.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; use clippy_utils::source::{IntoSpan, SpanRangeExt}; +use rustc_ast::{Local, TyKind}; use rustc_errors::Applicability; -use rustc_hir::{LetStmt, TyKind}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::declare_lint_pass; declare_clippy_lint! { @@ -26,14 +26,14 @@ } declare_lint_pass!(UnderscoreTyped => [LET_WITH_TYPE_UNDERSCORE]); -impl<'tcx> LateLintPass<'tcx> for UnderscoreTyped { - fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) { - if let Some(ty) = local.ty // Ensure that it has a type defined - && let TyKind::Infer(()) = &ty.kind // that type is '_' +impl EarlyLintPass for UnderscoreTyped { + fn check_local(&mut self, cx: &EarlyContext<'_>, local: &Local) { + if let Some(ty) = &local.ty // Ensure that it has a type defined + && let TyKind::Infer = ty.kind // that type is '_' && local.span.eq_ctxt(ty.span) - && let sm = cx.tcx.sess.source_map() + && let sm = cx.sess().source_map() && !local.span.in_external_macro(sm) - && !is_from_proc_macro(cx, ty) + && !is_from_proc_macro(cx, &**ty) { let span_to_remove = sm .span_extend_to_prev_char_before(ty.span, ':', true) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d468993e7444..10f0faa44088 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -743,7 +743,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co store.register_late_pass(|_| Box::new(missing_assert_message::MissingAssertMessage)); store.register_late_pass(|_| Box::new(needless_maybe_sized::NeedlessMaybeSized)); store.register_late_pass(|_| Box::new(redundant_async_block::RedundantAsyncBlock)); - store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped)); + store.register_early_pass(|| Box::new(let_with_type_underscore::UnderscoreTyped)); store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(conf))); store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct)); store.register_late_pass(move |_| Box::new(unnecessary_box_returns::UnnecessaryBoxReturns::new(conf)));