@@ -16,15 +16,16 @@ use rustc_abi::ExternAbi;
1616use rustc_ast as ast;
1717use rustc_ast:: AttrStyle ;
1818use rustc_ast:: ast:: {
19- AttrKind , Attribute , GenericArgs , IntTy , LitIntType , LitKind , StrStyle , TraitObjectSyntax , UintTy ,
19+ AttrKind , Attribute , BindingMode , GenericArgs , IntTy , LitIntType , LitKind , StrStyle , TraitObjectSyntax , UintTy ,
2020} ;
2121use rustc_ast:: token:: CommentKind ;
2222use rustc_hir:: intravisit:: FnKind ;
2323use rustc_hir:: {
2424 Block , BlockCheckMode , Body , BoundConstness , BoundPolarity , Closure , Destination , Expr , ExprKind , FieldDef ,
2525 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 ,
26+ MatchSource , MutTy , Node , PatExpr , PatExprKind , PatKind , Path , PolyTraitRef , QPath , Safety , TraitBoundModifiers ,
27+ TraitImplHeader , TraitItem , TraitItemKind , TraitRef , Ty , TyKind , UnOp , UnsafeSource , Variant , VariantData ,
28+ YieldSource ,
2829} ;
2930use rustc_lint:: { EarlyContext , LateContext , LintContext } ;
3031use rustc_middle:: ty:: TyCtxt ;
@@ -589,6 +590,99 @@ fn ident_search_pat(ident: Ident) -> (Pat, Pat) {
589590 ( Pat :: Sym ( ident. name ) , Pat :: Sym ( ident. name ) )
590591}
591592
593+ fn pat_search_pat ( tcx : TyCtxt < ' _ > , pat : & rustc_hir:: Pat < ' _ > ) -> ( Pat , Pat ) {
594+ match pat. kind {
595+ // Tuple patterns cannot show up in proc-macro checks
596+ PatKind :: Missing | PatKind :: Err ( _) | PatKind :: Tuple ( _, _) => ( Pat :: Str ( "" ) , Pat :: Str ( "" ) ) ,
597+ PatKind :: Wild => ( Pat :: Sym ( kw:: Underscore ) , Pat :: Sym ( kw:: Underscore ) ) ,
598+ PatKind :: Binding ( binding_mode, _, ident, Some ( end_pat) ) => {
599+ let start = if binding_mode == BindingMode :: NONE {
600+ ident_search_pat ( ident) . 0
601+ } else {
602+ Pat :: Str ( binding_mode. prefix_str ( ) )
603+ } ;
604+
605+ let ( _, end) = pat_search_pat ( tcx, end_pat) ;
606+ ( start, end)
607+ } ,
608+ PatKind :: Binding ( binding_mode, _, ident, None ) => {
609+ let ( s, end) = ident_search_pat ( ident) ;
610+ let start = if binding_mode == BindingMode :: NONE {
611+ s
612+ } else {
613+ Pat :: Str ( binding_mode. prefix_str ( ) )
614+ } ;
615+
616+ ( start, end)
617+ } ,
618+ PatKind :: Struct ( path, _, _) => {
619+ let ( start, _) = qpath_search_pat ( & path) ;
620+ ( start, Pat :: Str ( "}" ) )
621+ } ,
622+ PatKind :: TupleStruct ( path, _, _) => {
623+ let ( start, _) = qpath_search_pat ( & path) ;
624+ // This pattern cannot show up in proc-macro checks
625+ ( start, Pat :: Str ( "" ) )
626+ } ,
627+ PatKind :: Or ( plist) => {
628+ // documented invariant
629+ debug_assert ! ( plist. len( ) >= 2 ) ;
630+ let ( start, _) = pat_search_pat ( tcx, plist. first ( ) . unwrap ( ) ) ;
631+ let ( _, end) = pat_search_pat ( tcx, plist. last ( ) . unwrap ( ) ) ;
632+ ( start, end)
633+ } ,
634+ PatKind :: Never => ( Pat :: Str ( "!" ) , Pat :: Str ( "" ) ) ,
635+ PatKind :: Box ( p) => {
636+ let ( _, end) = pat_search_pat ( tcx, p) ;
637+ ( Pat :: Str ( "box" ) , end)
638+ } ,
639+ PatKind :: Deref ( _) => ( Pat :: Str ( "deref!" ) , Pat :: Str ( "" ) ) ,
640+ PatKind :: Ref ( p, _, _) => {
641+ let ( _, end) = pat_search_pat ( tcx, p) ;
642+ ( Pat :: Str ( "&" ) , end)
643+ } ,
644+ PatKind :: Expr ( expr) => pat_expr_search_pat ( expr) ,
645+ PatKind :: Guard ( pat, guard) => {
646+ let ( start, _) = pat_search_pat ( tcx, pat) ;
647+ let ( _, end) = expr_search_pat ( tcx, guard) ;
648+ ( start, end)
649+ } ,
650+ PatKind :: Range ( None , None , range) => match range {
651+ rustc_hir:: RangeEnd :: Included => ( Pat :: Str ( "..=" ) , Pat :: Str ( "" ) ) ,
652+ rustc_hir:: RangeEnd :: Excluded => ( Pat :: Str ( ".." ) , Pat :: Str ( "" ) ) ,
653+ } ,
654+ PatKind :: Range ( r_start, r_end, range) => {
655+ let start = match r_start {
656+ Some ( e) => pat_expr_search_pat ( e) . 0 ,
657+ None => match range {
658+ rustc_hir:: RangeEnd :: Included => Pat :: Str ( "..=" ) ,
659+ rustc_hir:: RangeEnd :: Excluded => Pat :: Str ( ".." ) ,
660+ } ,
661+ } ;
662+
663+ let end = match r_end {
664+ Some ( e) => pat_expr_search_pat ( e) . 1 ,
665+ None => match range {
666+ rustc_hir:: RangeEnd :: Included => Pat :: Str ( "..=" ) ,
667+ rustc_hir:: RangeEnd :: Excluded => Pat :: Str ( ".." ) ,
668+ } ,
669+ } ;
670+ ( start, end)
671+ } ,
672+ PatKind :: Slice ( _, _, _) => ( Pat :: Str ( "[" ) , Pat :: Str ( "]" ) ) ,
673+ }
674+ }
675+
676+ fn pat_expr_search_pat ( expr : & PatExpr < ' _ > ) -> ( Pat , Pat ) {
677+ match expr. kind {
678+ PatExprKind :: Lit { lit, negated } => {
679+ let ( start, end) = lit_search_pat ( & lit. node ) ;
680+ if negated { ( Pat :: Str ( "!" ) , end) } else { ( start, end) }
681+ } ,
682+ PatExprKind :: Path ( path) => qpath_search_pat ( & path) ,
683+ }
684+ }
685+
592686pub trait WithSearchPat < ' cx > {
593687 type Context : LintContext ;
594688 fn search_pat ( & self , cx : & Self :: Context ) -> ( Pat , Pat ) ;
@@ -618,6 +712,7 @@ impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ident) => ident_search_pat(
618712impl_with_search_pat ! ( ( _cx: LateContext <' tcx>, self : Lit ) => lit_search_pat( & self . node) ) ;
619713impl_with_search_pat ! ( ( _cx: LateContext <' tcx>, self : Path <' _>) => path_search_pat( self ) ) ;
620714impl_with_search_pat ! ( ( _cx: LateContext <' tcx>, self : PolyTraitRef <' _>) => poly_trait_ref_search_pat( self ) ) ;
715+ impl_with_search_pat ! ( ( cx: LateContext <' tcx>, self : rustc_hir:: Pat <' _>) => pat_search_pat( cx. tcx, self ) ) ;
621716
622717impl_with_search_pat ! ( ( _cx: EarlyContext <' tcx>, self : Attribute ) => attr_search_pat( self ) ) ;
623718impl_with_search_pat ! ( ( _cx: EarlyContext <' tcx>, self : ast:: Ty ) => ast_ty_search_pat( self ) ) ;
0 commit comments