Skip to content

Commit 6cdbc6b

Browse files
authored
Rollup merge of rust-lang#103354 - clubby789:escape-string-literals, r=compiler-errors
Escape string literals when fixing overlong char literal Fixes rust-lang#103323 ``@rustbot`` label +A-diagnostics +A-suggestion-diagnostics
2 parents 77f421c + 8762485 commit 6cdbc6b

File tree

8 files changed

+83
-8
lines changed

8 files changed

+83
-8
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -2271,6 +2271,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
22712271
struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
22722272
}
22732273
FailureCode::Error0308(failure_str) => {
2274+
fn escape_literal(s: &str) -> String {
2275+
let mut escaped = String::with_capacity(s.len());
2276+
let mut chrs = s.chars().peekable();
2277+
while let Some(first) = chrs.next() {
2278+
match (first, chrs.peek()) {
2279+
('\\', Some(&delim @ '"') | Some(&delim @ '\'')) => {
2280+
escaped.push('\\');
2281+
escaped.push(delim);
2282+
chrs.next();
2283+
}
2284+
('"' | '\'', _) => {
2285+
escaped.push('\\');
2286+
escaped.push(first)
2287+
}
2288+
(c, _) => escaped.push(c),
2289+
};
2290+
}
2291+
escaped
2292+
}
22742293
let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
22752294
if let Some((expected, found)) = trace.values.ty() {
22762295
match (expected.kind(), found.kind()) {
@@ -2292,7 +2311,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
22922311
err.span_suggestion(
22932312
span,
22942313
"if you meant to write a `char` literal, use single quotes",
2295-
format!("'{}'", code),
2314+
format!("'{}'", escape_literal(code)),
22962315
Applicability::MachineApplicable,
22972316
);
22982317
}
@@ -2307,7 +2326,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
23072326
err.span_suggestion(
23082327
span,
23092328
"if you meant to write a `str` literal, use double quotes",
2310-
format!("\"{}\"", code),
2329+
format!("\"{}\"", escape_literal(code)),
23112330
Applicability::MachineApplicable,
23122331
);
23132332
}

compiler/rustc_parse/src/lexer/unescape_error_reporting.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,26 @@ pub(crate) fn emit_unescape_error(
113113
} else {
114114
("", "if you meant to write a `str` literal, use double quotes")
115115
};
116-
116+
let mut escaped = String::with_capacity(lit.len());
117+
let mut chrs = lit.chars().peekable();
118+
while let Some(first) = chrs.next() {
119+
match (first, chrs.peek()) {
120+
('\\', Some('"')) => {
121+
escaped.push('\\');
122+
escaped.push('"');
123+
chrs.next();
124+
}
125+
('"', _) => {
126+
escaped.push('\\');
127+
escaped.push('"')
128+
}
129+
(c, _) => escaped.push(c),
130+
};
131+
}
117132
handler.span_suggestion(
118133
span_with_quotes,
119134
msg,
120-
format!("{}\"{}\"", prefix, lit),
135+
format!("{prefix}\"{escaped}\""),
121136
Applicability::MachineApplicable,
122137
);
123138
}

src/test/ui/inference/char-as-str-single.fixed

+1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
fn main() {
99
let _: char = 'a'; //~ ERROR mismatched types
1010
let _: char = '人'; //~ ERROR mismatched types
11+
let _: char = '\''; //~ ERROR mismatched types
1112
}

src/test/ui/inference/char-as-str-single.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
fn main() {
99
let _: char = "a"; //~ ERROR mismatched types
1010
let _: char = "人"; //~ ERROR mismatched types
11+
let _: char = "'"; //~ ERROR mismatched types
1112
}

src/test/ui/inference/char-as-str-single.stderr

+14-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@ help: if you meant to write a `char` literal, use single quotes
2424
LL | let _: char = '人';
2525
| ~~~~
2626

27-
error: aborting due to 2 previous errors
27+
error[E0308]: mismatched types
28+
--> $DIR/char-as-str-single.rs:11:19
29+
|
30+
LL | let _: char = "'";
31+
| ---- ^^^ expected `char`, found `&str`
32+
| |
33+
| expected due to this
34+
|
35+
help: if you meant to write a `char` literal, use single quotes
36+
|
37+
LL | let _: char = '\'';
38+
| ~~~~
39+
40+
error: aborting due to 3 previous errors
2841

2942
For more information about this error, try `rustc --explain E0308`.

src/test/ui/inference/str-as-char.fixed

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,7 @@
44
// run-rustfix
55

66
fn main() {
7-
let _: &str = "a"; //~ ERROR mismatched types
7+
let _: &str = "a"; //~ ERROR mismatched types
8+
let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
9+
let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
810
}

src/test/ui/inference/str-as-char.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,7 @@
44
// run-rustfix
55

66
fn main() {
7-
let _: &str = 'a'; //~ ERROR mismatched types
7+
let _: &str = 'a'; //~ ERROR mismatched types
8+
let _: &str = '"""'; //~ ERROR character literal may only contain one codepoint
9+
let _: &str = '\"\"\"'; //~ ERROR character literal may only contain one codepoint
810
}

src/test/ui/inference/str-as-char.stderr

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
error: character literal may only contain one codepoint
2+
--> $DIR/str-as-char.rs:8:19
3+
|
4+
LL | let _: &str = '"""';
5+
| ^^^^^
6+
|
7+
help: if you meant to write a `str` literal, use double quotes
8+
|
9+
LL | let _: &str = "\"\"\"";
10+
| ~~~~~~~~
11+
12+
error: character literal may only contain one codepoint
13+
--> $DIR/str-as-char.rs:9:19
14+
|
15+
LL | let _: &str = '\"\"\"';
16+
| ^^^^^^^^
17+
|
18+
help: if you meant to write a `str` literal, use double quotes
19+
|
20+
LL | let _: &str = "\"\"\"";
21+
| ~~~~~~~~
22+
123
error[E0308]: mismatched types
224
--> $DIR/str-as-char.rs:7:19
325
|
@@ -11,6 +33,6 @@ help: if you meant to write a `str` literal, use double quotes
1133
LL | let _: &str = "a";
1234
| ~~~
1335

14-
error: aborting due to previous error
36+
error: aborting due to 3 previous errors
1537

1638
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)