Skip to content

Commit 9857de2

Browse files
committed
shift no characters when using raw string literals
remove `find_skips` remove unnecessary variables
1 parent 0aaad9e commit 9857de2

File tree

5 files changed

+103
-76
lines changed

5 files changed

+103
-76
lines changed

compiler/rustc_parse_format/src/lib.rs

+74-76
Original file line numberDiff line numberDiff line change
@@ -818,96 +818,94 @@ fn find_skips_from_snippet(
818818
_ => return (vec![], false),
819819
};
820820

821-
fn find_skips(snippet: &str, is_raw: bool) -> Vec<usize> {
822-
let mut s = snippet.char_indices();
823-
let mut skips = vec![];
824-
while let Some((pos, c)) = s.next() {
825-
match (c, s.clone().next()) {
826-
// skip whitespace and empty lines ending in '\\'
827-
('\\', Some((next_pos, '\n'))) if !is_raw => {
828-
skips.push(pos);
829-
skips.push(next_pos);
830-
let _ = s.next();
821+
if str_style.is_some() {
822+
return (vec![], true);
823+
}
831824

832-
while let Some((pos, c)) = s.clone().next() {
833-
if matches!(c, ' ' | '\n' | '\t') {
834-
skips.push(pos);
835-
let _ = s.next();
836-
} else {
837-
break;
838-
}
839-
}
840-
}
841-
('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => {
842-
skips.push(next_pos);
843-
let _ = s.next();
844-
}
845-
('\\', Some((_, 'x'))) if !is_raw => {
846-
for _ in 0..3 {
847-
// consume `\xAB` literal
848-
if let Some((pos, _)) = s.next() {
849-
skips.push(pos);
850-
} else {
851-
break;
852-
}
825+
let snippet = &snippet[1..snippet.len() - 1];
826+
827+
let mut s = snippet.char_indices();
828+
let mut skips = vec![];
829+
while let Some((pos, c)) = s.next() {
830+
match (c, s.clone().next()) {
831+
// skip whitespace and empty lines ending in '\\'
832+
('\\', Some((next_pos, '\n'))) => {
833+
skips.push(pos);
834+
skips.push(next_pos);
835+
let _ = s.next();
836+
837+
while let Some((pos, c)) = s.clone().next() {
838+
if matches!(c, ' ' | '\n' | '\t') {
839+
skips.push(pos);
840+
let _ = s.next();
841+
} else {
842+
break;
853843
}
854844
}
855-
('\\', Some((_, 'u'))) if !is_raw => {
845+
}
846+
('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => {
847+
skips.push(next_pos);
848+
let _ = s.next();
849+
}
850+
('\\', Some((_, 'x'))) => {
851+
for _ in 0..3 {
852+
// consume `\xAB` literal
856853
if let Some((pos, _)) = s.next() {
857854
skips.push(pos);
855+
} else {
856+
break;
858857
}
859-
if let Some((next_pos, next_c)) = s.next() {
860-
if next_c == '{' {
861-
// consume up to 6 hexanumeric chars
862-
let digits_len =
863-
s.clone().take(6).take_while(|(_, c)| c.is_digit(16)).count();
864-
865-
let len_utf8 = s
866-
.as_str()
867-
.get(..digits_len)
868-
.and_then(|digits| u32::from_str_radix(digits, 16).ok())
869-
.and_then(char::from_u32)
870-
.map_or(1, char::len_utf8);
871-
872-
// Skip the digits, for chars that encode to more than 1 utf-8 byte
873-
// exclude as many digits as it is greater than 1 byte
874-
//
875-
// So for a 3 byte character, exclude 2 digits
876-
let required_skips =
877-
digits_len.saturating_sub(len_utf8.saturating_sub(1));
878-
879-
// skip '{' and '}' also
880-
for pos in (next_pos..).take(required_skips + 2) {
881-
skips.push(pos)
882-
}
858+
}
859+
}
860+
('\\', Some((_, 'u'))) => {
861+
if let Some((pos, _)) = s.next() {
862+
skips.push(pos);
863+
}
864+
if let Some((next_pos, next_c)) = s.next() {
865+
if next_c == '{' {
866+
// consume up to 6 hexanumeric chars
867+
let digits_len =
868+
s.clone().take(6).take_while(|(_, c)| c.is_digit(16)).count();
869+
870+
let len_utf8 = s
871+
.as_str()
872+
.get(..digits_len)
873+
.and_then(|digits| u32::from_str_radix(digits, 16).ok())
874+
.and_then(char::from_u32)
875+
.map_or(1, char::len_utf8);
876+
877+
// Skip the digits, for chars that encode to more than 1 utf-8 byte
878+
// exclude as many digits as it is greater than 1 byte
879+
//
880+
// So for a 3 byte character, exclude 2 digits
881+
let required_skips = digits_len.saturating_sub(len_utf8.saturating_sub(1));
882+
883+
// skip '{' and '}' also
884+
for pos in (next_pos..).take(required_skips + 2) {
885+
skips.push(pos)
886+
}
883887

884-
s.nth(digits_len);
885-
} else if next_c.is_digit(16) {
886-
skips.push(next_pos);
887-
// We suggest adding `{` and `}` when appropriate, accept it here as if
888-
// it were correct
889-
let mut i = 0; // consume up to 6 hexanumeric chars
890-
while let (Some((next_pos, c)), _) = (s.next(), i < 6) {
891-
if c.is_digit(16) {
892-
skips.push(next_pos);
893-
} else {
894-
break;
895-
}
896-
i += 1;
888+
s.nth(digits_len);
889+
} else if next_c.is_digit(16) {
890+
skips.push(next_pos);
891+
// We suggest adding `{` and `}` when appropriate, accept it here as if
892+
// it were correct
893+
let mut i = 0; // consume up to 6 hexanumeric chars
894+
while let (Some((next_pos, c)), _) = (s.next(), i < 6) {
895+
if c.is_digit(16) {
896+
skips.push(next_pos);
897+
} else {
898+
break;
897899
}
900+
i += 1;
898901
}
899902
}
900903
}
901-
_ => {}
902904
}
905+
_ => {}
903906
}
904-
skips
905907
}
906-
907-
let r_start = str_style.map_or(0, |r| r + 1);
908-
let r_end = str_style.unwrap_or(0);
909-
let s = &snippet[r_start + 1..snippet.len() - r_end - 1];
910-
(find_skips(s, str_style.is_some()), true)
908+
(skips, true)
911909
}
912910

913911
#[cfg(test)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
println!(r#"\'\'\'\'\'\'\'\'\'\'\'\'\'\'}"#); //~ ERROR invalid format string: unmatched `}` found
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: invalid format string: unmatched `}` found
2+
--> $DIR/format-raw-string-error.rs:2:45
3+
|
4+
LL | println!(r#"\'\'\'\'\'\'\'\'\'\'\'\'\'\'}"#);
5+
| ^ unmatched `}` in format string
6+
|
7+
= note: if you intended to print `}`, you can escape it using `}}`
8+
9+
error: aborting due to previous error
10+

src/test/ui/fmt/issue-104142.rs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn main() {
2+
println!(
3+
r#"
4+
\"\'}、"# //~ ERROR invalid format string: unmatched `}` found
5+
);
6+
}

src/test/ui/fmt/issue-104142.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: invalid format string: unmatched `}` found
2+
--> $DIR/issue-104142.rs:4:9
3+
|
4+
LL | \"\'}、"#
5+
| ^ unmatched `}` in format string
6+
|
7+
= note: if you intended to print `}`, you can escape it using `}}`
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)