diff options
| author | bors <bors@rust-lang.org> | 2021-09-21 22:07:32 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-09-21 22:07:32 +0000 |
| commit | d8d1d1059a7837551c0065fc060dcb806ad729ef (patch) | |
| tree | ad33e22ac8a336ba8f27beaaba0cd03b8b5d124c /compiler/rustc_parse | |
| parent | ac2d9fc509e36d1b32513744adf58c34bcc4f43c (diff) | |
| parent | a3e6c19acf12d5995407220721f4fe28452e51da (diff) | |
| download | rust-d8d1d1059a7837551c0065fc060dcb806ad729ef.tar.gz rust-d8d1d1059a7837551c0065fc060dcb806ad729ef.zip | |
Auto merge of #89158 - the8472:rollup-3e4ijth, r=the8472
Rollup of 12 pull requests Successful merges: - #88795 (Print a note if a character literal contains a variation selector) - #89015 (core::ascii::escape_default: reduce struct size) - #89078 (Cleanup: Remove needless reference in ParentHirIterator) - #89086 (Stabilize `Iterator::map_while`) - #89096 ([bootstrap] Improve the error message when `ninja` is not found to link to installation instructions) - #89113 (dont `.ensure()` the `thir_abstract_const` query call in `mir_build`) - #89114 (Fixes a technicality regarding the size of C's `char` type) - #89115 (:arrow_up: rust-analyzer) - #89126 (Fix ICE when `indirect_structural_match` is allowed) - #89141 (Impl `Error` for `FromSecsError` without foreign type) - #89142 (Fix match for placeholder region) - #89147 (add case for checking const refs in check_const_value_eq) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_parse')
| -rw-r--r-- | compiler/rustc_parse/src/lexer/unescape_error_reporting.rs | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index aa6b424ce2b..cef5b3a226b 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -3,7 +3,7 @@ use std::iter::once; use std::ops::Range; -use rustc_errors::{Applicability, Handler}; +use rustc_errors::{pluralize, Applicability, Handler}; use rustc_lexer::unescape::{EscapeError, Mode}; use rustc_span::{BytePos, Span}; @@ -49,24 +49,57 @@ pub(crate) fn emit_unescape_error( .emit(); } EscapeError::MoreThanOneChar => { - let (prefix, msg) = if mode.is_bytes() { - ("b", "if you meant to write a byte string literal, use double quotes") - } else { - ("", "if you meant to write a `str` literal, use double quotes") - }; + use unicode_normalization::{char::is_combining_mark, UnicodeNormalization}; - handler - .struct_span_err( - span_with_quotes, - "character literal may only contain one codepoint", - ) - .span_suggestion( + let mut has_help = false; + let mut handler = handler.struct_span_err( + span_with_quotes, + "character literal may only contain one codepoint", + ); + + if lit.chars().skip(1).all(|c| is_combining_mark(c)) { + let escaped_marks = + lit.chars().skip(1).map(|c| c.escape_default().to_string()).collect::<Vec<_>>(); + handler.span_note( + span, + &format!( + "this `{}` is followed by the combining mark{} `{}`", + lit.chars().next().unwrap(), + pluralize!(escaped_marks.len()), + escaped_marks.join(""), + ), + ); + let normalized = lit.nfc().to_string(); + if normalized.chars().count() == 1 { + has_help = true; + handler.span_suggestion( + span, + &format!( + "consider using the normalized form `{}` of this character", + normalized.chars().next().unwrap().escape_default() + ), + normalized, + Applicability::MachineApplicable, + ); + } + } + + if !has_help { + let (prefix, msg) = if mode.is_bytes() { + ("b", "if you meant to write a byte string literal, use double quotes") + } else { + ("", "if you meant to write a `str` literal, use double quotes") + }; + + handler.span_suggestion( span_with_quotes, msg, format!("{}\"{}\"", prefix, lit), Applicability::MachineApplicable, - ) - .emit(); + ); + } + + handler.emit(); } EscapeError::EscapeOnlyChar => { let (c, char_span) = last_char(); |
