@@ -13,7 +13,8 @@ declare_clippy_lint! {
1313 /// Checks for raw string literals where a string literal can be used instead.
1414 ///
1515 /// ### Why is this bad?
16- /// It's just unnecessary.
16+ /// It's just unnecessary, but there are many cases where using a raw string literal is more
17+ /// idiomatic than a string literal, so it's opt-in.
1718 ///
1819 /// ### Example
1920 /// ```rust
@@ -25,7 +26,7 @@ declare_clippy_lint! {
2526 /// ```
2627 #[ clippy:: version = "1.72.0" ]
2728 pub NEEDLESS_RAW_STRING ,
28- complexity ,
29+ restriction ,
2930 "suggests using a string literal when a raw string literal is unnecessary"
3031}
3132declare_clippy_lint ! {
@@ -46,7 +47,7 @@ declare_clippy_lint! {
4647 /// ```
4748 #[ clippy:: version = "1.72.0" ]
4849 pub NEEDLESS_RAW_STRING_HASHES ,
49- complexity ,
50+ style ,
5051 "suggests reducing the number of hashes around a raw string literal"
5152}
5253impl_lint_pass ! ( RawStrings => [ NEEDLESS_RAW_STRING , NEEDLESS_RAW_STRING_HASHES ] ) ;
@@ -59,7 +60,7 @@ impl EarlyLintPass for RawStrings {
5960 fn check_expr ( & mut self , cx : & EarlyContext < ' _ > , expr : & Expr ) {
6061 if !in_external_macro ( cx. sess ( ) , expr. span )
6162 && let ExprKind :: Lit ( lit) = expr. kind
62- && let LitKind :: StrRaw ( num ) | LitKind :: ByteStrRaw ( num ) | LitKind :: CStrRaw ( num ) = lit. kind
63+ && let LitKind :: StrRaw ( max ) | LitKind :: ByteStrRaw ( max ) | LitKind :: CStrRaw ( max ) = lit. kind
6364 {
6465 let prefix = match lit. kind {
6566 LitKind :: StrRaw ( ..) => "r" ,
@@ -86,14 +87,26 @@ impl EarlyLintPass for RawStrings {
8687 }
8788
8889 #[ expect( clippy:: cast_possible_truncation) ]
89- let req = lit. symbol . as_str ( ) . as_bytes ( )
90+ let req = lit
91+ . symbol
92+ . as_str ( )
93+ . as_bytes ( )
9094 . split ( |& b| b == b'"' )
9195 . skip ( 1 )
92- . map ( |bs| 1 + bs. iter ( ) . take_while ( |& & b| b == b'#' ) . count ( ) as u8 )
96+ . map_while ( |bs| {
97+ let num = bs. iter ( ) . take_while ( |& & b| b == b'#' ) . count ( ) as u8 ;
98+ if num. saturating_sub ( 1 ) == max {
99+ // Since `num - 1` is the max number of hashes it can have, we can
100+ // short-circuit with full confidence this is correct
101+ return None ;
102+ }
103+
104+ Some ( num + 1 )
105+ } )
93106 . max ( )
94107 . unwrap_or ( 0 ) ;
95108
96- if req < num {
109+ if req < max {
97110 let hashes = "#" . repeat ( req as usize ) ;
98111
99112 span_lint_and_sugg (
0 commit comments