1313//! if the span is not from a `macro_rules` based macro.
1414
1515use rustc_abi:: ExternAbi ;
16+ use rustc_ast as ast;
1617use rustc_ast:: AttrStyle ;
17- use rustc_ast:: ast:: { AttrKind , Attribute , IntTy , LitIntType , LitKind , StrStyle , TraitObjectSyntax , UintTy } ;
18+ use rustc_ast:: ast:: {
19+ AttrKind , Attribute , GenericArgs , IntTy , LitIntType , LitKind , StrStyle , TraitObjectSyntax , UintTy ,
20+ } ;
1821use rustc_ast:: token:: CommentKind ;
1922use rustc_hir:: intravisit:: FnKind ;
2023use rustc_hir:: {
@@ -26,7 +29,7 @@ use rustc_lint::{EarlyContext, LateContext, LintContext};
2629use rustc_middle:: ty:: TyCtxt ;
2730use rustc_session:: Session ;
2831use rustc_span:: symbol:: { Ident , kw} ;
29- use rustc_span:: { Span , Symbol } ;
32+ use rustc_span:: { Span , Symbol , sym } ;
3033
3134/// The search pattern to look for. Used by `span_matches_pat`
3235#[ derive( Clone ) ]
@@ -403,6 +406,7 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) {
403406 TyKind :: OpaqueDef ( ..) => ( Pat :: Str ( "impl" ) , Pat :: Str ( "" ) ) ,
404407 TyKind :: Path ( qpath) => qpath_search_pat ( & qpath) ,
405408 TyKind :: Infer ( ( ) ) => ( Pat :: Str ( "_" ) , Pat :: Str ( "_" ) ) ,
409+ TyKind :: UnsafeBinder ( binder_ty) => ( Pat :: Str ( "unsafe" ) , ty_search_pat ( binder_ty. inner_ty ) . 1 ) ,
406410 TyKind :: TraitObject ( _, tagged_ptr) if let TraitObjectSyntax :: Dyn = tagged_ptr. tag ( ) => {
407411 ( Pat :: Str ( "dyn" ) , Pat :: Str ( "" ) )
408412 } ,
@@ -411,6 +415,127 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) {
411415 }
412416}
413417
418+ fn ast_ty_search_pat ( ty : & ast:: Ty ) -> ( Pat , Pat ) {
419+ use ast:: { Extern , FnRetTy , MutTy , Safety , TraitObjectSyntax , TyKind } ;
420+
421+ match & ty. kind {
422+ TyKind :: Slice ( ..) | TyKind :: Array ( ..) => ( Pat :: Str ( "[" ) , Pat :: Str ( "]" ) ) ,
423+ TyKind :: Ptr ( MutTy { ty, .. } ) => ( Pat :: Str ( "*" ) , ast_ty_search_pat ( ty) . 1 ) ,
424+ TyKind :: Ref ( _, MutTy { ty, .. } ) | TyKind :: PinnedRef ( _, MutTy { ty, .. } ) => {
425+ ( Pat :: Str ( "&" ) , ast_ty_search_pat ( ty) . 1 )
426+ } ,
427+ TyKind :: FnPtr ( fn_ptr) => (
428+ if let Safety :: Unsafe ( _) = fn_ptr. safety {
429+ Pat :: Str ( "unsafe" )
430+ } else if let Extern :: Explicit ( strlit, _) = fn_ptr. ext
431+ && strlit. symbol == sym:: rust
432+ {
433+ Pat :: MultiStr ( & [ "fn" , "extern" ] )
434+ } else {
435+ Pat :: Str ( "extern" )
436+ } ,
437+ match & fn_ptr. decl . output {
438+ FnRetTy :: Default ( _) => {
439+ if let [ .., param] = & * fn_ptr. decl . inputs {
440+ ast_ty_search_pat ( & param. ty ) . 1
441+ } else {
442+ Pat :: Str ( "(" )
443+ }
444+ } ,
445+ FnRetTy :: Ty ( ty) => ast_ty_search_pat ( ty) . 1 ,
446+ } ,
447+ ) ,
448+ TyKind :: Never => ( Pat :: Str ( "!" ) , Pat :: Str ( "!" ) ) ,
449+ // Parenthesis are trimmed from the text before the search patterns are matched.
450+ // See: `span_matches_pat`
451+ TyKind :: Tup ( tup) => match & * * tup {
452+ [ ] => ( Pat :: Str ( ")" ) , Pat :: Str ( "(" ) ) ,
453+ [ ty] => ast_ty_search_pat ( ty) ,
454+ [ head, .., tail] => ( ast_ty_search_pat ( head) . 0 , ast_ty_search_pat ( tail) . 1 ) ,
455+ } ,
456+ TyKind :: ImplTrait ( ..) => ( Pat :: Str ( "impl" ) , Pat :: Str ( "" ) ) ,
457+ TyKind :: Path ( qself_path, path) => {
458+ let start = if qself_path. is_some ( ) {
459+ Pat :: Str ( "<" )
460+ } else if let Some ( first) = path. segments . first ( ) {
461+ ident_search_pat ( first. ident ) . 0
462+ } else {
463+ // this shouldn't be possible, but sure
464+ Pat :: Str ( "" )
465+ } ;
466+ let end = if let Some ( last) = path. segments . last ( ) {
467+ match last. args . as_deref ( ) {
468+ // last `>` in `std::foo::Bar<T>`
469+ Some ( GenericArgs :: AngleBracketed ( _) ) => Pat :: Str ( ">" ) ,
470+ Some ( GenericArgs :: Parenthesized ( par_args) ) => match & par_args. output {
471+ FnRetTy :: Default ( _) => {
472+ if let Some ( last) = par_args. inputs . last ( ) {
473+ // `B` in `(A, B)` -- `)` gets stripped
474+ ast_ty_search_pat ( last) . 1
475+ } else {
476+ // `(` in `()` -- `)` gets stripped
477+ Pat :: Str ( "(" )
478+ }
479+ } ,
480+ // `C` in `(A, B) -> C`
481+ FnRetTy :: Ty ( ty) => ast_ty_search_pat ( ty) . 1 ,
482+ } ,
483+ // last `..` in `(..)` -- `)` gets stripped
484+ Some ( GenericArgs :: ParenthesizedElided ( _) ) => Pat :: Str ( ".." ) ,
485+ // `bar` in `std::foo::bar`
486+ None => ident_search_pat ( last. ident ) . 1 ,
487+ }
488+ } else {
489+ // this shouldn't be possible, but sure
490+ #[ allow(
491+ clippy:: collapsible_else_if,
492+ reason = "we want to keep these cases together, since they are both impossible"
493+ ) ]
494+ if qself_path. is_some ( ) {
495+ // last `>` in `<Vec as IntoIterator>`
496+ Pat :: Str ( ">" )
497+ } else {
498+ Pat :: Str ( "" )
499+ }
500+ } ;
501+ ( start, end)
502+ } ,
503+ TyKind :: Infer => ( Pat :: Str ( "_" ) , Pat :: Str ( "_" ) ) ,
504+ TyKind :: Paren ( ty) => ast_ty_search_pat ( ty) ,
505+ TyKind :: UnsafeBinder ( binder_ty) => ( Pat :: Str ( "unsafe" ) , ast_ty_search_pat ( & binder_ty. inner_ty ) . 1 ) ,
506+ TyKind :: TraitObject ( _, trait_obj_syntax) => {
507+ if let TraitObjectSyntax :: Dyn = trait_obj_syntax {
508+ ( Pat :: Str ( "dyn" ) , Pat :: Str ( "" ) )
509+ } else {
510+ // NOTE: `TraitObject` is incomplete. It will always return true then.
511+ ( Pat :: Str ( "" ) , Pat :: Str ( "" ) )
512+ }
513+ } ,
514+ TyKind :: MacCall ( mac_call) => {
515+ let start = if let Some ( first) = mac_call. path . segments . first ( ) {
516+ ident_search_pat ( first. ident ) . 0
517+ } else {
518+ Pat :: Str ( "" )
519+ } ;
520+ ( start, Pat :: Str ( "" ) )
521+ } ,
522+
523+ // implicit, so has no contents to match against
524+ TyKind :: ImplicitSelf
525+
526+ // experimental
527+ |TyKind :: Pat ( ..)
528+
529+ // unused
530+ | TyKind :: CVarArgs
531+ | TyKind :: Typeof ( _)
532+
533+ // placeholder
534+ | TyKind :: Dummy
535+ | TyKind :: Err ( _) => ( Pat :: Str ( "" ) , Pat :: Str ( "" ) ) ,
536+ }
537+ }
538+
414539fn ident_search_pat ( ident : Ident ) -> ( Pat , Pat ) {
415540 ( Pat :: Sym ( ident. name ) , Pat :: Sym ( ident. name ) )
416541}
@@ -445,6 +570,7 @@ impl_with_search_pat!((_cx: LateContext<'tcx>, self: Lit) => lit_search_pat(&sel
445570impl_with_search_pat ! ( ( _cx: LateContext <' tcx>, self : Path <' _>) => path_search_pat( self ) ) ;
446571
447572impl_with_search_pat ! ( ( _cx: EarlyContext <' tcx>, self : Attribute ) => attr_search_pat( self ) ) ;
573+ impl_with_search_pat ! ( ( _cx: EarlyContext <' tcx>, self : ast:: Ty ) => ast_ty_search_pat( self ) ) ;
448574
449575impl < ' cx > WithSearchPat < ' cx > for ( & FnKind < ' cx > , & Body < ' cx > , HirId , Span ) {
450576 type Context = LateContext < ' cx > ;
0 commit comments