13
13
//! if the span is not from a `macro_rules` based macro.
14
14
15
15
use rustc_abi:: ExternAbi ;
16
+ use rustc_ast as ast;
16
17
use 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
+ } ;
18
21
use rustc_ast:: token:: CommentKind ;
19
22
use rustc_hir:: intravisit:: FnKind ;
20
23
use rustc_hir:: {
@@ -26,7 +29,7 @@ use rustc_lint::{EarlyContext, LateContext, LintContext};
26
29
use rustc_middle:: ty:: TyCtxt ;
27
30
use rustc_session:: Session ;
28
31
use rustc_span:: symbol:: { Ident , kw} ;
29
- use rustc_span:: { Span , Symbol } ;
32
+ use rustc_span:: { Span , Symbol , sym } ;
30
33
31
34
/// The search pattern to look for. Used by `span_matches_pat`
32
35
#[ derive( Clone ) ]
@@ -403,6 +406,7 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) {
403
406
TyKind :: OpaqueDef ( ..) => ( Pat :: Str ( "impl" ) , Pat :: Str ( "" ) ) ,
404
407
TyKind :: Path ( qpath) => qpath_search_pat ( & qpath) ,
405
408
TyKind :: Infer ( ( ) ) => ( Pat :: Str ( "_" ) , Pat :: Str ( "_" ) ) ,
409
+ TyKind :: UnsafeBinder ( binder_ty) => ( Pat :: Str ( "unsafe" ) , ty_search_pat ( binder_ty. inner_ty ) . 1 ) ,
406
410
TyKind :: TraitObject ( _, tagged_ptr) if let TraitObjectSyntax :: Dyn = tagged_ptr. tag ( ) => {
407
411
( Pat :: Str ( "dyn" ) , Pat :: Str ( "" ) )
408
412
} ,
@@ -411,6 +415,127 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) {
411
415
}
412
416
}
413
417
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
+
414
539
fn ident_search_pat ( ident : Ident ) -> ( Pat , Pat ) {
415
540
( Pat :: Sym ( ident. name ) , Pat :: Sym ( ident. name ) )
416
541
}
@@ -445,6 +570,7 @@ impl_with_search_pat!((_cx: LateContext<'tcx>, self: Lit) => lit_search_pat(&sel
445
570
impl_with_search_pat ! ( ( _cx: LateContext <' tcx>, self : Path <' _>) => path_search_pat( self ) ) ;
446
571
447
572
impl_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 ) ) ;
448
574
449
575
impl < ' cx > WithSearchPat < ' cx > for ( & FnKind < ' cx > , & Body < ' cx > , HirId , Span ) {
450
576
type Context = LateContext < ' cx > ;
0 commit comments