@@ -21,10 +21,10 @@ use rustc_ast::ast::{
21
21
use rustc_ast:: token:: CommentKind ;
22
22
use rustc_hir:: intravisit:: FnKind ;
23
23
use rustc_hir:: {
24
- Block , BlockCheckMode , Body , Closure , Destination , Expr , ExprKind , FieldDef , FnHeader , FnRetTy , HirId , Impl ,
25
- ImplItem , ImplItemImplKind , ImplItemKind , IsAuto , Item , ItemKind , Lit , LoopSource , MatchSource , MutTy , Node , Path ,
26
- QPath , Safety , TraitImplHeader , TraitItem , TraitItemKind , Ty , TyKind , UnOp , UnsafeSource , Variant , VariantData ,
27
- YieldSource ,
24
+ Block , BlockCheckMode , Body , BoundConstness , BoundPolarity , Closure , Destination , Expr , ExprKind , FieldDef ,
25
+ FnHeader , FnRetTy , HirId , Impl , ImplItem , ImplItemImplKind , ImplItemKind , IsAuto , Item , ItemKind , Lit , LoopSource ,
26
+ MatchSource , MutTy , Node , Path , PolyTraitRef , QPath , Safety , TraitBoundModifiers , TraitImplHeader , TraitItem ,
27
+ TraitItemKind , TraitRef , Ty , TyKind , UnOp , UnsafeSource , Variant , VariantData , YieldSource ,
28
28
} ;
29
29
use rustc_lint:: { EarlyContext , LateContext , LintContext } ;
30
30
use rustc_middle:: ty:: TyCtxt ;
@@ -537,6 +537,44 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) {
537
537
}
538
538
}
539
539
540
+ // NOTE: can't `impl WithSearchPat for TraitRef`, because `TraitRef` doesn't have a `span` field
541
+ // (nor a method)
542
+ fn trait_ref_search_pat ( trait_ref : & TraitRef < ' _ > ) -> ( Pat , Pat ) {
543
+ path_search_pat ( trait_ref. path )
544
+ }
545
+
546
+ fn poly_trait_ref_search_pat ( poly_trait_ref : & PolyTraitRef < ' _ > ) -> ( Pat , Pat ) {
547
+ // NOTE: unfortunately we can't use `bound_generic_params` to see whether the pattern starts with
548
+ // `for<..>`, because if it's empty, we could have either `for<>` (nothing bound), or
549
+ // no `for` at all
550
+ let PolyTraitRef {
551
+ modifiers : TraitBoundModifiers { constness, polarity } ,
552
+ trait_ref,
553
+ ..
554
+ } = poly_trait_ref;
555
+
556
+ let trait_ref_search_pat = trait_ref_search_pat ( trait_ref) ;
557
+
558
+ #[ expect(
559
+ clippy:: unnecessary_lazy_evaluations,
560
+ reason = "the closure in `or_else` has `match polarity`, which isn't free"
561
+ ) ]
562
+ let start = match constness {
563
+ BoundConstness :: Never => None ,
564
+ BoundConstness :: Maybe ( _) => Some ( Pat :: Str ( "[const]" ) ) ,
565
+ BoundConstness :: Always ( _) => Some ( Pat :: Str ( "const" ) ) ,
566
+ }
567
+ . or_else ( || match polarity {
568
+ BoundPolarity :: Negative ( _) => Some ( Pat :: Str ( "!" ) ) ,
569
+ BoundPolarity :: Maybe ( _) => Some ( Pat :: Str ( "?" ) ) ,
570
+ BoundPolarity :: Positive => None ,
571
+ } )
572
+ . unwrap_or ( trait_ref_search_pat. 0 ) ;
573
+ let end = trait_ref_search_pat. 1 ;
574
+
575
+ ( start, end)
576
+ }
577
+
540
578
fn ident_search_pat ( ident : Ident ) -> ( Pat , Pat ) {
541
579
( Pat :: Sym ( ident. name ) , Pat :: Sym ( ident. name ) )
542
580
}
@@ -569,6 +607,7 @@ impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ty<'_>) => ty_search_pat(se
569
607
impl_with_search_pat ! ( ( _cx: LateContext <' tcx>, self : Ident ) => ident_search_pat( * self ) ) ;
570
608
impl_with_search_pat ! ( ( _cx: LateContext <' tcx>, self : Lit ) => lit_search_pat( & self . node) ) ;
571
609
impl_with_search_pat ! ( ( _cx: LateContext <' tcx>, self : Path <' _>) => path_search_pat( self ) ) ;
610
+ impl_with_search_pat ! ( ( _cx: LateContext <' tcx>, self : PolyTraitRef <' _>) => poly_trait_ref_search_pat( self ) ) ;
572
611
573
612
impl_with_search_pat ! ( ( _cx: EarlyContext <' tcx>, self : Attribute ) => attr_search_pat( self ) ) ;
574
613
impl_with_search_pat ! ( ( _cx: EarlyContext <' tcx>, self : ast:: Ty ) => ast_ty_search_pat( self ) ) ;
0 commit comments