1212//! code was written, and check if the span contains that text. Note this will only work correctly
1313//! if the span is not from a `macro_rules` based macro.
1414
15- use rustc_ast:: ast:: { AttrKind , Attribute , IntTy , LitIntType , LitKind , StrStyle , UintTy } ;
15+ use rustc_ast:: ast:: { AttrKind , Attribute , IntTy , LitIntType , LitKind , StrStyle , TraitObjectSyntax , UintTy } ;
1616use rustc_ast:: token:: CommentKind ;
1717use rustc_ast:: AttrStyle ;
1818use rustc_hir:: intravisit:: FnKind ;
1919use rustc_hir:: {
20- Block , BlockCheckMode , Body , Closure , Destination , Expr , ExprKind , FieldDef , FnHeader , HirId , Impl , ImplItem ,
21- ImplItemKind , IsAuto , Item , ItemKind , LoopSource , MatchSource , MutTy , Node , QPath , TraitItem , TraitItemKind , Ty ,
22- TyKind , UnOp , UnsafeSource , Unsafety , Variant , VariantData , YieldSource ,
20+ Block , BlockCheckMode , Body , Closure , Destination , Expr , ExprKind , FieldDef , FnHeader , FnRetTy , HirId , Impl ,
21+ ImplItem , ImplItemKind , IsAuto , Item , ItemKind , LoopSource , MatchSource , MutTy , Node , QPath , TraitItem ,
22+ TraitItemKind , Ty , TyKind , UnOp , UnsafeSource , Unsafety , Variant , VariantData , YieldSource ,
2323} ;
24- use rustc_lint :: { LateContext , LintContext } ;
24+ use crate :: { LateContext , LintContext } ;
2525use rustc_middle:: ty:: TyCtxt ;
2626use rustc_session:: Session ;
2727use rustc_span:: symbol:: Ident ;
@@ -33,8 +33,6 @@ use rustc_target::spec::abi::Abi;
3333pub enum Pat {
3434 /// A single string.
3535 Str ( & ' static str ) ,
36- /// A single string.
37- OwnedStr ( String ) ,
3836 /// Any of the given strings.
3937 MultiStr ( & ' static [ & ' static str ] ) ,
4038 /// Any of the given strings.
@@ -47,7 +45,7 @@ pub enum Pat {
4745
4846/// Checks if the start and the end of the span's text matches the patterns. This will return false
4947/// if the span crosses multiple files or if source is not available.
50- fn span_matches_pat ( sess : & Session , span : Span , start_pat : Pat , end_pat : Pat ) -> bool {
48+ pub fn span_matches_pat ( sess : & Session , span : Span , start_pat : Pat , end_pat : Pat ) -> bool {
5149 let pos = sess. source_map ( ) . lookup_byte_offset ( span. lo ( ) ) ;
5250 let Some ( ref src) = pos. sf . src else {
5351 return false ;
@@ -59,14 +57,12 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) ->
5957 let end_str = s. trim_end_matches ( |c : char | c. is_whitespace ( ) || c == ')' || c == ',' ) ;
6058 ( match start_pat {
6159 Pat :: Str ( text) => start_str. starts_with ( text) ,
62- Pat :: OwnedStr ( text) => start_str. starts_with ( & text) ,
6360 Pat :: MultiStr ( texts) => texts. iter ( ) . any ( |s| start_str. starts_with ( s) ) ,
6461 Pat :: OwnedMultiStr ( texts) => texts. iter ( ) . any ( |s| start_str. starts_with ( s) ) ,
6562 Pat :: Sym ( sym) => start_str. starts_with ( sym. as_str ( ) ) ,
6663 Pat :: Num => start_str. as_bytes ( ) . first ( ) . map_or ( false , u8:: is_ascii_digit) ,
6764 } && match end_pat {
6865 Pat :: Str ( text) => end_str. ends_with ( text) ,
69- Pat :: OwnedStr ( text) => end_str. starts_with ( & text) ,
7066 Pat :: MultiStr ( texts) => texts. iter ( ) . any ( |s| start_str. ends_with ( s) ) ,
7167 Pat :: OwnedMultiStr ( texts) => texts. iter ( ) . any ( |s| start_str. starts_with ( s) ) ,
7268 Pat :: Sym ( sym) => end_str. ends_with ( sym. as_str ( ) ) ,
@@ -125,6 +121,7 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) {
125121fn expr_search_pat ( tcx : TyCtxt < ' _ > , e : & Expr < ' _ > ) -> ( Pat , Pat ) {
126122 match e. kind {
127123 ExprKind :: ConstBlock ( _) => ( Pat :: Str ( "const" ) , Pat :: Str ( "}" ) ) ,
124+ // Parenthesis are skipped before the patterns are matched.
128125 ExprKind :: Tup ( [ ] ) => ( Pat :: Str ( ")" ) , Pat :: Str ( "(" ) ) ,
129126 ExprKind :: Unary ( UnOp :: Deref , e) => ( Pat :: Str ( "*" ) , expr_search_pat ( tcx, e) . 1 ) ,
130127 ExprKind :: Unary ( UnOp :: Not , e) => ( Pat :: Str ( "!" ) , expr_search_pat ( tcx, e) . 1 ) ,
@@ -286,21 +283,17 @@ fn fn_kind_pat(tcx: TyCtxt<'_>, kind: &FnKind<'_>, body: &Body<'_>, hir_id: HirI
286283fn attr_search_pat ( attr : & Attribute ) -> ( Pat , Pat ) {
287284 match attr. kind {
288285 AttrKind :: Normal ( ..) => {
289- let mut pat = if matches ! ( attr. style, AttrStyle :: Outer ) {
290- ( Pat :: Str ( "#[" ) , Pat :: Str ( "]" ) )
291- } else {
292- ( Pat :: Str ( "#![" ) , Pat :: Str ( "]" ) )
293- } ;
294-
295- if let Some ( ident) = attr. ident ( ) && let Pat :: Str ( old_pat) = pat. 0 {
286+ if let Some ( ident) = attr. ident ( ) {
296287 // TODO: I feel like it's likely we can use `Cow` instead but this will require quite a bit of
297288 // refactoring
298289 // NOTE: This will likely have false positives, like `allow = 1`
299- pat. 0 = Pat :: OwnedMultiStr ( vec ! [ ident. to_string( ) , old_pat. to_owned( ) ] ) ;
300- pat. 1 = Pat :: Str ( "" ) ;
290+ (
291+ Pat :: OwnedMultiStr ( vec ! [ ident. to_string( ) , "#" . to_owned( ) ] ) ,
292+ Pat :: Str ( "" ) ,
293+ )
294+ } else {
295+ ( Pat :: Str ( "#" ) , Pat :: Str ( "]" ) )
301296 }
302-
303- pat
304297 } ,
305298 AttrKind :: DocComment ( _kind @ CommentKind :: Line , ..) => {
306299 if matches ! ( attr. style, AttrStyle :: Outer ) {
@@ -322,32 +315,41 @@ fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) {
322315fn ty_search_pat ( ty : & Ty < ' _ > ) -> ( Pat , Pat ) {
323316 match ty. kind {
324317 TyKind :: Slice ( ..) | TyKind :: Array ( ..) => ( Pat :: Str ( "[" ) , Pat :: Str ( "]" ) ) ,
325- TyKind :: Ptr ( MutTy { mutbl, ty } ) => (
326- if mutbl. is_mut ( ) {
327- Pat :: Str ( "*const" )
328- } else {
329- Pat :: Str ( "*mut" )
330- } ,
331- ty_search_pat ( ty) . 1 ,
332- ) ,
318+ TyKind :: Ptr ( MutTy { ty, .. } ) => ( Pat :: Str ( "*" ) , ty_search_pat ( ty) . 1 ) ,
333319 TyKind :: Ref ( _, MutTy { ty, .. } ) => ( Pat :: Str ( "&" ) , ty_search_pat ( ty) . 1 ) ,
334320 TyKind :: BareFn ( bare_fn) => (
335- Pat :: OwnedStr ( format ! ( "{}{} fn" , bare_fn. unsafety. prefix_str( ) , bare_fn. abi. name( ) ) ) ,
336- ty_search_pat ( ty) . 1 ,
321+ if bare_fn. unsafety == Unsafety :: Unsafe {
322+ Pat :: Str ( "unsafe" )
323+ } else if bare_fn. abi != Abi :: Rust {
324+ Pat :: Str ( "extern" )
325+ } else {
326+ Pat :: MultiStr ( & [ "fn" , "extern" ] )
327+ } ,
328+ match bare_fn. decl . output {
329+ FnRetTy :: DefaultReturn ( _) => {
330+ if let [ .., ty] = bare_fn. decl . inputs {
331+ ty_search_pat ( ty) . 1
332+ } else {
333+ Pat :: Str ( "(" )
334+ }
335+ } ,
336+ FnRetTy :: Return ( ty) => ty_search_pat ( ty) . 1 ,
337+ } ,
337338 ) ,
338- TyKind :: Never => ( Pat :: Str ( "!" ) , Pat :: Str ( "" ) ) ,
339- TyKind :: Tup ( ..) => ( Pat :: Str ( "(" ) , Pat :: Str ( ")" ) ) ,
339+ TyKind :: Never => ( Pat :: Str ( "!" ) , Pat :: Str ( "!" ) ) ,
340+ // Parenthesis are skipped before the patterns are matched.
341+ TyKind :: Tup ( [ ] ) => ( Pat :: Str ( ")" ) , Pat :: Str ( "(" ) ) ,
342+ TyKind :: Tup ( [ ty] ) => ty_search_pat ( ty) ,
343+ TyKind :: Tup ( [ head, .., tail] ) => ( ty_search_pat ( head) . 0 , ty_search_pat ( tail) . 1 ) ,
340344 TyKind :: OpaqueDef ( ..) => ( Pat :: Str ( "impl" ) , Pat :: Str ( "" ) ) ,
341345 TyKind :: Path ( qpath) => qpath_search_pat ( & qpath) ,
342- // NOTE: This is missing `TraitObject`. It will always return true then.
346+ TyKind :: Infer => ( Pat :: Str ( "_" ) , Pat :: Str ( "_" ) ) ,
347+ TyKind :: TraitObject ( _, _, TraitObjectSyntax :: Dyn ) => ( Pat :: Str ( "dyn" ) , Pat :: Str ( "" ) ) ,
348+ // NOTE: `TraitObject` is incomplete. It will always return true then.
343349 _ => ( Pat :: Str ( "" ) , Pat :: Str ( "" ) ) ,
344350 }
345351}
346352
347- fn ident_search_pat ( ident : Ident ) -> ( Pat , Pat ) {
348- ( Pat :: OwnedStr ( ident. name . as_str ( ) . to_owned ( ) ) , Pat :: Str ( "" ) )
349- }
350-
351353pub trait WithSearchPat < ' cx > {
352354 type Context : LintContext ;
353355 fn search_pat ( & self , cx : & Self :: Context ) -> ( Pat , Pat ) ;
@@ -406,7 +408,7 @@ impl<'cx> WithSearchPat<'cx> for Ident {
406408 type Context = LateContext < ' cx > ;
407409
408410 fn search_pat ( & self , _cx : & Self :: Context ) -> ( Pat , Pat ) {
409- ident_search_pat ( * self )
411+ ( Pat :: Sym ( self . name ) , Pat :: Sym ( self . name ) )
410412 }
411413
412414 fn span ( & self ) -> Span {
@@ -431,4 +433,4 @@ pub fn is_span_match(cx: &impl LintContext, span: Span) -> bool {
431433/// Checks if the span actually refers to an if expression
432434pub fn is_span_if ( cx : & impl LintContext , span : Span ) -> bool {
433435 span_matches_pat ( cx. sess ( ) , span, Pat :: Str ( "if" ) , Pat :: Str ( "}" ) )
434- }
436+ }
0 commit comments