Skip to content

Commit c28deba

Browse files
committed
Update raw_strings.rs
Revert "new lints for visibility" This reverts commit 0e5a537. new lints for visibility
1 parent fb43d3a commit c28deba

File tree

2 files changed

+43
-18
lines changed

2 files changed

+43
-18
lines changed

clippy_lints/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10511051
store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold)));
10521052
store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit));
10531053
store.register_late_pass(|_| Box::new(incorrect_impls::IncorrectImpls));
1054+
let needless_raw_string_hashes_allow_one = conf.allow_one_hash_in_raw_string;
1055+
store.register_early_pass(move || {
1056+
Box::new(raw_strings::RawStrings {
1057+
needless_raw_string_hashes_allow_one,
1058+
})
1059+
});
10541060
// add lints here, do not remove this comment, it's used in `new_lint`
10551061
}
10561062

clippy_lints/src/raw_strings.rs

+37-18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::{iter::once, ops::ControlFlow};
2+
13
use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet};
24
use rustc_ast::{
35
ast::{Expr, ExprKind},
@@ -62,6 +64,7 @@ impl EarlyLintPass for RawStrings {
6264
&& let ExprKind::Lit(lit) = expr.kind
6365
&& let LitKind::StrRaw(max) | LitKind::ByteStrRaw(max) | LitKind::CStrRaw(max) = lit.kind
6466
{
67+
let str = lit.symbol.as_str();
6568
let prefix = match lit.kind {
6669
LitKind::StrRaw(..) => "r",
6770
LitKind::ByteStrRaw(..) => "br",
@@ -72,7 +75,7 @@ impl EarlyLintPass for RawStrings {
7275
return;
7376
}
7477

75-
if !lit.symbol.as_str().contains(['\\', '"']) {
78+
if !str.contains(['\\', '"']) {
7679
span_lint_and_sugg(
7780
cx,
7881
NEEDLESS_RAW_STRING,
@@ -86,25 +89,41 @@ impl EarlyLintPass for RawStrings {
8689
return;
8790
}
8891

89-
#[expect(clippy::cast_possible_truncation)]
90-
let req = lit
91-
.symbol
92-
.as_str()
93-
.as_bytes()
94-
.split(|&b| b == b'"')
95-
.skip(1)
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;
92+
let req = {
93+
let mut following_quote = false;
94+
let mut req = 0;
95+
// `once` so a raw string ending in hashes is still checked
96+
let num = str.as_bytes().iter().chain(once(&0)).try_fold(0u8, |acc, &b| {
97+
match b {
98+
b'"' => (following_quote, req) = (true, 1),
99+
// I'm a bit surprised the compiler didn't optimize this out, there's no
100+
// branch but it still ends up doing an unnecessary comparison, it's:
101+
// - cmp r9b,1h
102+
// - sbb cl,-1h
103+
// which will add 1 if it's true. With this change, it becomes:
104+
// - add cl,r9b
105+
// isn't that so much nicer?
106+
b'#' => req += u8::from(following_quote),
107+
_ => {
108+
if following_quote {
109+
following_quote = false;
110+
111+
if req == max {
112+
return ControlFlow::Break(req);
113+
}
114+
115+
return ControlFlow::Continue(acc.max(req));
116+
}
117+
},
102118
}
103119

104-
Some(num + 1)
105-
})
106-
.max()
107-
.unwrap_or(0);
120+
ControlFlow::Continue(acc)
121+
});
122+
123+
match num {
124+
ControlFlow::Continue(num) | ControlFlow::Break(num) => num,
125+
}
126+
};
108127

109128
if req < max {
110129
let hashes = "#".repeat(req as usize);

0 commit comments

Comments
 (0)