Skip to content

Commit

Permalink
Rollup merge of rust-lang#103354 - clubby789:escape-string-literals, …
Browse files Browse the repository at this point in the history
…r=compiler-errors

Escape string literals when fixing overlong char literal

Fixes rust-lang#103323

``@rustbot`` label +A-diagnostics +A-suggestion-diagnostics
  • Loading branch information
notriddle committed Oct 22, 2022
2 parents 77f421c + 8762485 commit 6cdbc6b
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 8 deletions.
23 changes: 21 additions & 2 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2271,6 +2271,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
}
FailureCode::Error0308(failure_str) => {
fn escape_literal(s: &str) -> String {
let mut escaped = String::with_capacity(s.len());
let mut chrs = s.chars().peekable();
while let Some(first) = chrs.next() {
match (first, chrs.peek()) {
('\\', Some(&delim @ '"') | Some(&delim @ '\'')) => {
escaped.push('\\');
escaped.push(delim);
chrs.next();
}
('"' | '\'', _) => {
escaped.push('\\');
escaped.push(first)
}
(c, _) => escaped.push(c),
};
}
escaped
}
let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
if let Some((expected, found)) = trace.values.ty() {
match (expected.kind(), found.kind()) {
Expand All @@ -2292,7 +2311,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err.span_suggestion(
span,
"if you meant to write a `char` literal, use single quotes",
format!("'{}'", code),
format!("'{}'", escape_literal(code)),
Applicability::MachineApplicable,
);
}
Expand All @@ -2307,7 +2326,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err.span_suggestion(
span,
"if you meant to write a `str` literal, use double quotes",
format!("\"{}\"", code),
format!("\"{}\"", escape_literal(code)),
Applicability::MachineApplicable,
);
}
Expand Down
19 changes: 17 additions & 2 deletions compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,26 @@ pub(crate) fn emit_unescape_error(
} else {
("", "if you meant to write a `str` literal, use double quotes")
};

let mut escaped = String::with_capacity(lit.len());
let mut chrs = lit.chars().peekable();
while let Some(first) = chrs.next() {
match (first, chrs.peek()) {
('\\', Some('"')) => {
escaped.push('\\');
escaped.push('"');
chrs.next();
}
('"', _) => {
escaped.push('\\');
escaped.push('"')
}
(c, _) => escaped.push(c),
};
}
handler.span_suggestion(
span_with_quotes,
msg,
format!("{}\"{}\"", prefix, lit),
format!("{prefix}\"{escaped}\""),
Applicability::MachineApplicable,
);
}
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/inference/char-as-str-single.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
fn main() {
let _: char = 'a'; //~ ERROR mismatched types
let _: char = '人'; //~ ERROR mismatched types
let _: char = '\''; //~ ERROR mismatched types
}
1 change: 1 addition & 0 deletions src/test/ui/inference/char-as-str-single.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
fn main() {
let _: char = "a"; //~ ERROR mismatched types
let _: char = "人"; //~ ERROR mismatched types
let _: char = "'"; //~ ERROR mismatched types
}
15 changes: 14 additions & 1 deletion src/test/ui/inference/char-as-str-single.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@ help: if you meant to write a `char` literal, use single quotes
LL | let _: char = '人';
| ~~~~

error: aborting due to 2 previous errors
error[E0308]: mismatched types
--> $DIR/char-as-str-single.rs:11:19
|
LL | let _: char = "'";
| ---- ^^^ expected `char`, found `&str`
| |
| expected due to this
|
help: if you meant to write a `char` literal, use single quotes
|
LL | let _: char = '\'';
| ~~~~

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0308`.
4 changes: 3 additions & 1 deletion src/test/ui/inference/str-as-char.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
// run-rustfix

fn main() {
let _: &str = "a"; //~ ERROR mismatched types
let _: &str = "a"; //~ ERROR mismatched types
let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
}
4 changes: 3 additions & 1 deletion src/test/ui/inference/str-as-char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
// run-rustfix

fn main() {
let _: &str = 'a'; //~ ERROR mismatched types
let _: &str = 'a'; //~ ERROR mismatched types
let _: &str = '"""'; //~ ERROR character literal may only contain one codepoint
let _: &str = '\"\"\"'; //~ ERROR character literal may only contain one codepoint
}
24 changes: 23 additions & 1 deletion src/test/ui/inference/str-as-char.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
error: character literal may only contain one codepoint
--> $DIR/str-as-char.rs:8:19
|
LL | let _: &str = '"""';
| ^^^^^
|
help: if you meant to write a `str` literal, use double quotes
|
LL | let _: &str = "\"\"\"";
| ~~~~~~~~

error: character literal may only contain one codepoint
--> $DIR/str-as-char.rs:9:19
|
LL | let _: &str = '\"\"\"';
| ^^^^^^^^
|
help: if you meant to write a `str` literal, use double quotes
|
LL | let _: &str = "\"\"\"";
| ~~~~~~~~

error[E0308]: mismatched types
--> $DIR/str-as-char.rs:7:19
|
Expand All @@ -11,6 +33,6 @@ help: if you meant to write a `str` literal, use double quotes
LL | let _: &str = "a";
| ~~~

error: aborting due to previous error
error: aborting due to 3 previous errors

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

0 comments on commit 6cdbc6b

Please sign in to comment.