diff --git a/Cargo.lock b/Cargo.lock
index 0b1b01557ba94..146070cf16713 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3882,6 +3882,7 @@ dependencies = [
  "termcolor",
  "termize",
  "tracing",
+ "unicode-width",
  "windows",
 ]
 
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index 2fff9f2de50fb..cc114fdcd8c35 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -26,6 +26,7 @@ serde_json = "1.0.59"
 termcolor = "1.2.0"
 termize = "0.1.1"
 tracing = "0.1"
+unicode-width = "0.1.4"
 # tidy-alphabetical-end
 
 [target.'cfg(windows)'.dependencies.windows]
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 58220c6549005..aa47ca166764b 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -8,7 +8,7 @@
 //! The output types are defined in `rustc_session::config::ErrorOutputType`.
 
 use rustc_span::source_map::SourceMap;
-use rustc_span::{char_width, FileLines, FileName, SourceFile, Span};
+use rustc_span::{FileLines, FileName, SourceFile, Span};
 
 use crate::snippet::{
     Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
@@ -677,7 +677,10 @@ impl HumanEmitter {
             .skip(left)
             .take_while(|ch| {
                 // Make sure that the trimming on the right will fall within the terminal width.
-                let next = char_width(*ch);
+                // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char`
+                // is. For now, just accept that sometimes the code line will be longer than
+                // desired.
+                let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1);
                 if taken + next > right - left {
                     return false;
                 }
@@ -739,7 +742,11 @@ impl HumanEmitter {
         let left = margin.left(source_string.len());
 
         // Account for unicode characters of width !=0 that were removed.
-        let left = source_string.chars().take(left).map(|ch| char_width(ch)).sum();
+        let left = source_string
+            .chars()
+            .take(left)
+            .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1))
+            .sum();
 
         self.draw_line(
             buffer,
@@ -2032,7 +2039,7 @@ impl HumanEmitter {
                     let sub_len: usize =
                         if is_whitespace_addition { &part.snippet } else { part.snippet.trim() }
                             .chars()
-                            .map(|ch| char_width(ch))
+                            .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1))
                             .sum();
 
                     let offset: isize = offsets
@@ -2069,8 +2076,11 @@ impl HumanEmitter {
                     }
 
                     // length of the code after substitution
-                    let full_sub_len =
-                        part.snippet.chars().map(|ch| char_width(ch)).sum::<usize>() as isize;
+                    let full_sub_len = part
+                        .snippet
+                        .chars()
+                        .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1))
+                        .sum::<usize>() as isize;
 
                     // length of the code to be substituted
                     let snippet_len = span_end_pos as isize - span_start_pos as isize;
@@ -2558,53 +2568,18 @@ fn num_decimal_digits(num: usize) -> usize {
 }
 
 // We replace some characters so the CLI output is always consistent and underlines aligned.
-// Keep the following list in sync with `rustc_span::char_width`.
 const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[
-    ('\t', "    "),    // We do our own tab replacement
+    ('\t', "    "),   // We do our own tab replacement
     ('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters.
-    ('\u{202A}', "�"), // The following unicode text flow control characters are inconsistently
-    ('\u{202B}', "�"), // supported across CLIs and can cause confusion due to the bytes on disk
-    ('\u{202D}', "�"), // not corresponding to the visible source code, so we replace them always.
-    ('\u{202E}', "�"),
-    ('\u{2066}', "�"),
-    ('\u{2067}', "�"),
-    ('\u{2068}', "�"),
-    ('\u{202C}', "�"),
-    ('\u{2069}', "�"),
-    // In terminals without Unicode support the following will be garbled, but in *all* terminals
-    // the underlying codepoint will be as well. We could gate this replacement behind a "unicode
-    // support" gate.
-    ('\u{0000}', "␀"),
-    ('\u{0001}', "␁"),
-    ('\u{0002}', "␂"),
-    ('\u{0003}', "␃"),
-    ('\u{0004}', "␄"),
-    ('\u{0005}', "␅"),
-    ('\u{0006}', "␆"),
-    ('\u{0007}', "␇"),
-    ('\u{0008}', "␈"),
-    ('\u{000B}', "␋"),
-    ('\u{000C}', "␌"),
-    ('\u{000D}', "␍"),
-    ('\u{000E}', "␎"),
-    ('\u{000F}', "␏"),
-    ('\u{0010}', "␐"),
-    ('\u{0011}', "␑"),
-    ('\u{0012}', "␒"),
-    ('\u{0013}', "␓"),
-    ('\u{0014}', "␔"),
-    ('\u{0015}', "␕"),
-    ('\u{0016}', "␖"),
-    ('\u{0017}', "␗"),
-    ('\u{0018}', "␘"),
-    ('\u{0019}', "␙"),
-    ('\u{001A}', "␚"),
-    ('\u{001B}', "␛"),
-    ('\u{001C}', "␜"),
-    ('\u{001D}', "␝"),
-    ('\u{001E}', "␞"),
-    ('\u{001F}', "␟"),
-    ('\u{007F}', "␡"),
+    ('\u{202A}', ""), // The following unicode text flow control characters are inconsistently
+    ('\u{202B}', ""), // supported across CLIs and can cause confusion due to the bytes on disk
+    ('\u{202D}', ""), // not corresponding to the visible source code, so we replace them always.
+    ('\u{202E}', ""),
+    ('\u{2066}', ""),
+    ('\u{2067}', ""),
+    ('\u{2068}', ""),
+    ('\u{202C}', ""),
+    ('\u{2069}', ""),
 ];
 
 fn normalize_whitespace(str: &str) -> String {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 9874624ae2592..e5e430bc90dcd 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1728,6 +1728,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                     source_len,
                     lines,
                     multibyte_chars,
+                    non_narrow_chars,
                     normalized_pos,
                     stable_id,
                     ..
@@ -1779,6 +1780,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                     self.cnum,
                     lines,
                     multibyte_chars,
+                    non_narrow_chars,
                     normalized_pos,
                     source_file_index,
                 );
diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs
index 39da5e395c42d..5bd4fe04848fb 100644
--- a/compiler/rustc_query_system/src/ich/impls_syntax.rs
+++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs
@@ -73,6 +73,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
             source_len: _,
             lines: _,
             ref multibyte_chars,
+            ref non_narrow_chars,
             ref normalized_pos,
         } = *self;
 
@@ -97,6 +98,11 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
             char_pos.hash_stable(hcx, hasher);
         }
 
+        non_narrow_chars.len().hash_stable(hcx, hasher);
+        for &char_pos in non_narrow_chars.iter() {
+            char_pos.hash_stable(hcx, hasher);
+        }
+
         normalized_pos.len().hash_stable(hcx, hasher);
         for &char_pos in normalized_pos.iter() {
             char_pos.hash_stable(hcx, hasher);
diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs
index ba7e0cec5bd80..d9e1ebaf0bce0 100644
--- a/compiler/rustc_span/src/analyze_source_file.rs
+++ b/compiler/rustc_span/src/analyze_source_file.rs
@@ -1,4 +1,5 @@
 use super::*;
+use unicode_width::UnicodeWidthChar;
 
 #[cfg(test)]
 mod tests;
@@ -8,12 +9,15 @@ mod tests;
 ///
 /// This function will use an SSE2 enhanced implementation if hardware support
 /// is detected at runtime.
-pub fn analyze_source_file(src: &str) -> (Vec<RelativeBytePos>, Vec<MultiByteChar>) {
+pub fn analyze_source_file(
+    src: &str,
+) -> (Vec<RelativeBytePos>, Vec<MultiByteChar>, Vec<NonNarrowChar>) {
     let mut lines = vec![RelativeBytePos::from_u32(0)];
     let mut multi_byte_chars = vec![];
+    let mut non_narrow_chars = vec![];
 
     // Calls the right implementation, depending on hardware support available.
-    analyze_source_file_dispatch(src, &mut lines, &mut multi_byte_chars);
+    analyze_source_file_dispatch(src, &mut lines, &mut multi_byte_chars, &mut non_narrow_chars);
 
     // The code above optimistically registers a new line *after* each \n
     // it encounters. If that point is already outside the source_file, remove
@@ -26,7 +30,7 @@ pub fn analyze_source_file(src: &str) -> (Vec<RelativeBytePos>, Vec<MultiByteCha
         }
     }
 
-    (lines, multi_byte_chars)
+    (lines, multi_byte_chars, non_narrow_chars)
 }
 
 cfg_match! {
@@ -35,10 +39,11 @@ cfg_match! {
             src: &str,
             lines: &mut Vec<RelativeBytePos>,
             multi_byte_chars: &mut Vec<MultiByteChar>,
+            non_narrow_chars: &mut Vec<NonNarrowChar>,
         ) {
             if is_x86_feature_detected!("sse2") {
                 unsafe {
-                    analyze_source_file_sse2(src, lines, multi_byte_chars);
+                    analyze_source_file_sse2(src, lines, multi_byte_chars, non_narrow_chars);
                 }
             } else {
                 analyze_source_file_generic(
@@ -47,6 +52,7 @@ cfg_match! {
                     RelativeBytePos::from_u32(0),
                     lines,
                     multi_byte_chars,
+                    non_narrow_chars,
                 );
             }
         }
@@ -60,6 +66,7 @@ cfg_match! {
             src: &str,
             lines: &mut Vec<RelativeBytePos>,
             multi_byte_chars: &mut Vec<MultiByteChar>,
+            non_narrow_chars: &mut Vec<NonNarrowChar>,
         ) {
             #[cfg(target_arch = "x86")]
             use std::arch::x86::*;
@@ -152,6 +159,7 @@ cfg_match! {
                     RelativeBytePos::from_usize(scan_start),
                     lines,
                     multi_byte_chars,
+                    non_narrow_chars,
                 );
             }
 
@@ -164,6 +172,7 @@ cfg_match! {
                     RelativeBytePos::from_usize(tail_start),
                     lines,
                     multi_byte_chars,
+                    non_narrow_chars,
                 );
             }
         }
@@ -174,6 +183,7 @@ cfg_match! {
             src: &str,
             lines: &mut Vec<RelativeBytePos>,
             multi_byte_chars: &mut Vec<MultiByteChar>,
+            non_narrow_chars: &mut Vec<NonNarrowChar>,
         ) {
             analyze_source_file_generic(
                 src,
@@ -181,6 +191,7 @@ cfg_match! {
                 RelativeBytePos::from_u32(0),
                 lines,
                 multi_byte_chars,
+                non_narrow_chars,
             );
         }
     }
@@ -194,6 +205,7 @@ fn analyze_source_file_generic(
     output_offset: RelativeBytePos,
     lines: &mut Vec<RelativeBytePos>,
     multi_byte_chars: &mut Vec<MultiByteChar>,
+    non_narrow_chars: &mut Vec<NonNarrowChar>,
 ) -> usize {
     assert!(src.len() >= scan_len);
     let mut i = 0;
@@ -215,8 +227,16 @@ fn analyze_source_file_generic(
 
             let pos = RelativeBytePos::from_usize(i) + output_offset;
 
-            if let b'\n' = byte {
-                lines.push(pos + RelativeBytePos(1));
+            match byte {
+                b'\n' => {
+                    lines.push(pos + RelativeBytePos(1));
+                }
+                b'\t' => {
+                    non_narrow_chars.push(NonNarrowChar::Tab(pos));
+                }
+                _ => {
+                    non_narrow_chars.push(NonNarrowChar::ZeroWidth(pos));
+                }
             }
         } else if byte >= 127 {
             // The slow path:
@@ -232,6 +252,14 @@ fn analyze_source_file_generic(
                 let mbc = MultiByteChar { pos, bytes: char_len as u8 };
                 multi_byte_chars.push(mbc);
             }
+
+            // Assume control characters are zero width.
+            // FIXME: How can we decide between `width` and `width_cjk`?
+            let char_width = UnicodeWidthChar::width(c).unwrap_or(0);
+
+            if char_width != 1 {
+                non_narrow_chars.push(NonNarrowChar::new(pos, char_width));
+            }
         }
 
         i += char_len;
diff --git a/compiler/rustc_span/src/analyze_source_file/tests.rs b/compiler/rustc_span/src/analyze_source_file/tests.rs
index e4a24239d8ea1..0c77d080c17a0 100644
--- a/compiler/rustc_span/src/analyze_source_file/tests.rs
+++ b/compiler/rustc_span/src/analyze_source_file/tests.rs
@@ -4,10 +4,11 @@ macro_rules! test {
     (case: $test_name:ident,
      text: $text:expr,
      lines: $lines:expr,
-     multi_byte_chars: $multi_byte_chars:expr,) => {
+     multi_byte_chars: $multi_byte_chars:expr,
+     non_narrow_chars: $non_narrow_chars:expr,) => {
         #[test]
         fn $test_name() {
-            let (lines, multi_byte_chars) = analyze_source_file($text);
+            let (lines, multi_byte_chars, non_narrow_chars) = analyze_source_file($text);
 
             let expected_lines: Vec<RelativeBytePos> =
                 $lines.into_iter().map(RelativeBytePos).collect();
@@ -20,6 +21,13 @@ macro_rules! test {
                 .collect();
 
             assert_eq!(multi_byte_chars, expected_mbcs);
+
+            let expected_nncs: Vec<NonNarrowChar> = $non_narrow_chars
+                .into_iter()
+                .map(|(pos, width)| NonNarrowChar::new(RelativeBytePos(pos), width))
+                .collect();
+
+            assert_eq!(non_narrow_chars, expected_nncs);
         }
     };
 }
@@ -29,6 +37,7 @@ test!(
     text: "",
     lines: vec![],
     multi_byte_chars: vec![],
+    non_narrow_chars: vec![],
 );
 
 test!(
@@ -36,6 +45,7 @@ test!(
     text: "a\nc",
     lines: vec![0, 2],
     multi_byte_chars: vec![],
+    non_narrow_chars: vec![],
 );
 
 test!(
@@ -43,6 +53,7 @@ test!(
     text: "012345678\nabcdef012345678\na",
     lines: vec![0, 10, 26],
     multi_byte_chars: vec![],
+    non_narrow_chars: vec![],
 );
 
 test!(
@@ -50,6 +61,7 @@ test!(
     text: "01234β789\nbcdef0123456789abcdef",
     lines: vec![0, 11],
     multi_byte_chars: vec![(5, 2)],
+    non_narrow_chars: vec![],
 );
 
 test!(
@@ -57,6 +69,7 @@ test!(
     text: "01234\u{07}6789\nbcdef0123456789abcdef",
     lines: vec![0, 11],
     multi_byte_chars: vec![],
+    non_narrow_chars: vec![(5, 0)],
 );
 
 test!(
@@ -64,6 +77,7 @@ test!(
     text: "aβc",
     lines: vec![0],
     multi_byte_chars: vec![(1, 2)],
+    non_narrow_chars: vec![],
 );
 
 test!(
@@ -71,6 +85,7 @@ test!(
     text: "0123456789abcΔf012345β",
     lines: vec![0],
     multi_byte_chars: vec![(13, 2), (22, 2)],
+    non_narrow_chars: vec![],
 );
 
 test!(
@@ -78,6 +93,7 @@ test!(
     text: "0123456789abcdeΔ123456789abcdef01234",
     lines: vec![0],
     multi_byte_chars: vec![(15, 2)],
+    non_narrow_chars: vec![],
 );
 
 test!(
@@ -85,6 +101,7 @@ test!(
     text: "0123456789abcdeΔ....",
     lines: vec![0],
     multi_byte_chars: vec![(15, 2)],
+    non_narrow_chars: vec![],
 );
 
 test!(
@@ -92,6 +109,7 @@ test!(
     text: "0\t2",
     lines: vec![0],
     multi_byte_chars: vec![],
+    non_narrow_chars: vec![(1, 4)],
 );
 
 test!(
@@ -99,6 +117,7 @@ test!(
     text: "01\t3456789abcdef01234567\u{07}9",
     lines: vec![0],
     multi_byte_chars: vec![],
+    non_narrow_chars: vec![(2, 4), (24, 0)],
 );
 
 test!(
@@ -106,4 +125,5 @@ test!(
     text: "01\t345\n789abcΔf01234567\u{07}9\nbcΔf",
     lines: vec![0, 7, 27],
     multi_byte_chars: vec![(13, 2), (29, 2)],
+    non_narrow_chars: vec![(2, 4), (24, 0)],
 );
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 7c8ac3be4beca..266956d63d710 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -1345,6 +1345,68 @@ pub struct MultiByteChar {
     pub bytes: u8,
 }
 
+/// Identifies an offset of a non-narrow character in a `SourceFile`.
+#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug, HashStable_Generic)]
+pub enum NonNarrowChar {
+    /// Represents a zero-width character.
+    ZeroWidth(RelativeBytePos),
+    /// Represents a wide (full-width) character.
+    Wide(RelativeBytePos),
+    /// Represents a tab character, represented visually with a width of 4 characters.
+    Tab(RelativeBytePos),
+}
+
+impl NonNarrowChar {
+    fn new(pos: RelativeBytePos, width: usize) -> Self {
+        match width {
+            0 => NonNarrowChar::ZeroWidth(pos),
+            2 => NonNarrowChar::Wide(pos),
+            4 => NonNarrowChar::Tab(pos),
+            _ => panic!("width {width} given for non-narrow character"),
+        }
+    }
+
+    /// Returns the relative offset of the character in the `SourceFile`.
+    pub fn pos(&self) -> RelativeBytePos {
+        match *self {
+            NonNarrowChar::ZeroWidth(p) | NonNarrowChar::Wide(p) | NonNarrowChar::Tab(p) => p,
+        }
+    }
+
+    /// Returns the width of the character, 0 (zero-width) or 2 (wide).
+    pub fn width(&self) -> usize {
+        match *self {
+            NonNarrowChar::ZeroWidth(_) => 0,
+            NonNarrowChar::Wide(_) => 2,
+            NonNarrowChar::Tab(_) => 4,
+        }
+    }
+}
+
+impl Add<RelativeBytePos> for NonNarrowChar {
+    type Output = Self;
+
+    fn add(self, rhs: RelativeBytePos) -> Self {
+        match self {
+            NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos + rhs),
+            NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos + rhs),
+            NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos + rhs),
+        }
+    }
+}
+
+impl Sub<RelativeBytePos> for NonNarrowChar {
+    type Output = Self;
+
+    fn sub(self, rhs: RelativeBytePos) -> Self {
+        match self {
+            NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos - rhs),
+            NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos - rhs),
+            NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos - rhs),
+        }
+    }
+}
+
 /// Identifies an offset of a character that was normalized away from `SourceFile`.
 #[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug, HashStable_Generic)]
 pub struct NormalizedPos {
@@ -1519,6 +1581,8 @@ pub struct SourceFile {
     pub lines: FreezeLock<SourceFileLines>,
     /// Locations of multi-byte characters in the source code.
     pub multibyte_chars: Vec<MultiByteChar>,
+    /// Width of characters that are not narrow in the source code.
+    pub non_narrow_chars: Vec<NonNarrowChar>,
     /// Locations of characters removed during normalization.
     pub normalized_pos: Vec<NormalizedPos>,
     /// A hash of the filename & crate-id, used for uniquely identifying source
@@ -1540,6 +1604,7 @@ impl Clone for SourceFile {
             source_len: self.source_len,
             lines: self.lines.clone(),
             multibyte_chars: self.multibyte_chars.clone(),
+            non_narrow_chars: self.non_narrow_chars.clone(),
             normalized_pos: self.normalized_pos.clone(),
             stable_id: self.stable_id,
             cnum: self.cnum,
@@ -1614,6 +1679,7 @@ impl<S: SpanEncoder> Encodable<S> for SourceFile {
         }
 
         self.multibyte_chars.encode(s);
+        self.non_narrow_chars.encode(s);
         self.stable_id.encode(s);
         self.normalized_pos.encode(s);
         self.cnum.encode(s);
@@ -1640,6 +1706,7 @@ impl<D: SpanDecoder> Decodable<D> for SourceFile {
             }
         };
         let multibyte_chars: Vec<MultiByteChar> = Decodable::decode(d);
+        let non_narrow_chars: Vec<NonNarrowChar> = Decodable::decode(d);
         let stable_id = Decodable::decode(d);
         let normalized_pos: Vec<NormalizedPos> = Decodable::decode(d);
         let cnum: CrateNum = Decodable::decode(d);
@@ -1654,6 +1721,7 @@ impl<D: SpanDecoder> Decodable<D> for SourceFile {
             external_src: FreezeLock::frozen(ExternalSource::Unneeded),
             lines: FreezeLock::new(lines),
             multibyte_chars,
+            non_narrow_chars,
             normalized_pos,
             stable_id,
             cnum,
@@ -1741,7 +1809,8 @@ impl SourceFile {
         let source_len = src.len();
         let source_len = u32::try_from(source_len).map_err(|_| OffsetOverflowError)?;
 
-        let (lines, multibyte_chars) = analyze_source_file::analyze_source_file(&src);
+        let (lines, multibyte_chars, non_narrow_chars) =
+            analyze_source_file::analyze_source_file(&src);
 
         Ok(SourceFile {
             name,
@@ -1752,6 +1821,7 @@ impl SourceFile {
             source_len: RelativeBytePos::from_u32(source_len),
             lines: FreezeLock::frozen(SourceFileLines::Lines(lines)),
             multibyte_chars,
+            non_narrow_chars,
             normalized_pos,
             stable_id,
             cnum: LOCAL_CRATE,
@@ -2060,45 +2130,41 @@ impl SourceFile {
         let pos = self.relative_position(pos);
         let (line, col_or_chpos) = self.lookup_file_pos(pos);
         if line > 0 {
-            let Some(code) = self.get_line(line - 1) else {
-                // If we don't have the code available, it is ok as a fallback to return the bytepos
-                // instead of the "display" column, which is only used to properly show underlines
-                // in the terminal.
-                // FIXME: we'll want better handling of this in the future for the sake of tools
-                // that want to use the display col instead of byte offsets to modify Rust code, but
-                // that is a problem for another day, the previous code was already incorrect for
-                // both displaying *and* third party tools using the json output naïvely.
-                tracing::info!("couldn't find line {line} {:?}", self.name);
-                return (line, col_or_chpos, col_or_chpos.0);
+            let col = col_or_chpos;
+            let linebpos = self.lines()[line - 1];
+            let col_display = {
+                let start_width_idx = self
+                    .non_narrow_chars
+                    .binary_search_by_key(&linebpos, |x| x.pos())
+                    .unwrap_or_else(|x| x);
+                let end_width_idx = self
+                    .non_narrow_chars
+                    .binary_search_by_key(&pos, |x| x.pos())
+                    .unwrap_or_else(|x| x);
+                let special_chars = end_width_idx - start_width_idx;
+                let non_narrow: usize = self.non_narrow_chars[start_width_idx..end_width_idx]
+                    .iter()
+                    .map(|x| x.width())
+                    .sum();
+                col.0 - special_chars + non_narrow
             };
-            let display_col = code.chars().take(col_or_chpos.0).map(|ch| char_width(ch)).sum();
-            (line, col_or_chpos, display_col)
+            (line, col, col_display)
         } else {
-            // This is never meant to happen?
-            (0, col_or_chpos, col_or_chpos.0)
+            let chpos = col_or_chpos;
+            let col_display = {
+                let end_width_idx = self
+                    .non_narrow_chars
+                    .binary_search_by_key(&pos, |x| x.pos())
+                    .unwrap_or_else(|x| x);
+                let non_narrow: usize =
+                    self.non_narrow_chars[0..end_width_idx].iter().map(|x| x.width()).sum();
+                chpos.0 - end_width_idx + non_narrow
+            };
+            (0, chpos, col_display)
         }
     }
 }
 
-pub fn char_width(ch: char) -> usize {
-    // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. For now,
-    // just accept that sometimes the code line will be longer than desired.
-    match ch {
-        '\t' => 4,
-        // Keep the following list in sync with `rustc_errors::emitter::OUTPUT_REPLACEMENTS`. These
-        // are control points that we replace before printing with a visible codepoint for the sake
-        // of being able to point at them with underlines.
-        '\u{0000}' | '\u{0001}' | '\u{0002}' | '\u{0003}' | '\u{0004}' | '\u{0005}'
-        | '\u{0006}' | '\u{0007}' | '\u{0008}' | '\u{000B}' | '\u{000C}' | '\u{000D}'
-        | '\u{000E}' | '\u{000F}' | '\u{0010}' | '\u{0011}' | '\u{0012}' | '\u{0013}'
-        | '\u{0014}' | '\u{0015}' | '\u{0016}' | '\u{0017}' | '\u{0018}' | '\u{0019}'
-        | '\u{001A}' | '\u{001B}' | '\u{001C}' | '\u{001D}' | '\u{001E}' | '\u{001F}'
-        | '\u{007F}' | '\u{202A}' | '\u{202B}' | '\u{202D}' | '\u{202E}' | '\u{2066}'
-        | '\u{2067}' | '\u{2068}' | '\u{202C}' | '\u{2069}' => 1,
-        _ => unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1),
-    }
-}
-
 /// Normalizes the source code and records the normalizations.
 fn normalize_src(src: &mut String) -> Vec<NormalizedPos> {
     let mut normalized_pos = vec![];
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 14c157a0111ce..fb212d67997a7 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -330,6 +330,7 @@ impl SourceMap {
         cnum: CrateNum,
         file_local_lines: FreezeLock<SourceFileLines>,
         multibyte_chars: Vec<MultiByteChar>,
+        non_narrow_chars: Vec<NonNarrowChar>,
         normalized_pos: Vec<NormalizedPos>,
         metadata_index: u32,
     ) -> Lrc<SourceFile> {
@@ -347,6 +348,7 @@ impl SourceMap {
             source_len,
             lines: file_local_lines,
             multibyte_chars,
+            non_narrow_chars,
             normalized_pos,
             stable_id,
             cnum,
diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs
index 0c818b94b85a3..dcb02da371921 100644
--- a/compiler/rustc_span/src/source_map/tests.rs
+++ b/compiler/rustc_span/src/source_map/tests.rs
@@ -232,6 +232,7 @@ fn t10() {
         source_len,
         lines,
         multibyte_chars,
+        non_narrow_chars,
         normalized_pos,
         stable_id,
         ..
@@ -245,6 +246,7 @@ fn t10() {
         CrateNum::ZERO,
         FreezeLock::new(lines.read().clone()),
         multibyte_chars,
+        non_narrow_chars,
         normalized_pos,
         0,
     );
diff --git a/tests/rustdoc-ui/doctest/test-compile-fail3.stderr b/tests/rustdoc-ui/doctest/test-compile-fail3.stderr
index 09d78b2f34673..1ed4554225116 100644
--- a/tests/rustdoc-ui/doctest/test-compile-fail3.stderr
+++ b/tests/rustdoc-ui/doctest/test-compile-fail3.stderr
@@ -2,7 +2,7 @@ error[E0765]: unterminated double quote string
  --> $DIR/test-compile-fail3.rs:3:1
   |
 3 | "fail
-  | ^^^^^
+  | ^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/codemap_tests/tab_2.stderr b/tests/ui/codemap_tests/tab_2.stderr
index b22c7b4266517..4f9a937155dde 100644
--- a/tests/ui/codemap_tests/tab_2.stderr
+++ b/tests/ui/codemap_tests/tab_2.stderr
@@ -4,7 +4,7 @@ error[E0765]: unterminated double quote string
 LL |                   """;
    |  ___________________^
 LL | | }
-   | |_^
+   | |__^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0601.stderr b/tests/ui/error-codes/E0601.stderr
index c051bc0b31a0f..41a4a8f7dbbaa 100644
--- a/tests/ui/error-codes/E0601.stderr
+++ b/tests/ui/error-codes/E0601.stderr
@@ -2,7 +2,7 @@ error[E0601]: `main` function not found in crate `E0601`
   --> $DIR/E0601.rs:1:37
    |
 LL |
-   |                                    ^ consider adding a `main` function to `$DIR/E0601.rs`
+   |                                     ^ consider adding a `main` function to `$DIR/E0601.rs`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-44078.stderr b/tests/ui/issues/issue-44078.stderr
index 41106b29aad78..3e12de34e11ee 100644
--- a/tests/ui/issues/issue-44078.stderr
+++ b/tests/ui/issues/issue-44078.stderr
@@ -4,7 +4,7 @@ error[E0765]: unterminated double quote string
 LL |       "😊"";
    |  _________^
 LL | | }
-   | |_^
+   | |__^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr b/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr
index 841d5236edefa..da80991c727f7 100644
--- a/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr
+++ b/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr
@@ -1,31 +1,31 @@
 error: bare CR not allowed in doc-comment
   --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:3:32
    |
-LL | /// doc comment with bare CR: '␍'
+LL | /// doc comment with bare CR: '
'
    |                                ^
 
 error: bare CR not allowed in block doc-comment
   --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:7:38
    |
-LL | /** block doc comment with bare CR: '␍' */
+LL | /** block doc comment with bare CR: '
' */
    |                                      ^
 
 error: bare CR not allowed in doc-comment
   --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:12:36
    |
-LL |     //! doc comment with bare CR: '␍'
+LL |     //! doc comment with bare CR: '
'
    |                                    ^
 
 error: bare CR not allowed in block doc-comment
   --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:15:42
    |
-LL |     /*! block doc comment with bare CR: '␍' */
+LL |     /*! block doc comment with bare CR: '
' */
    |                                          ^
 
 error: bare CR not allowed in string, use `\r` instead
   --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:19:18
    |
-LL |     let _s = "foo␍bar";
+LL |     let _s = "foo
bar";
    |                  ^
    |
 help: escape the character
@@ -36,13 +36,13 @@ LL |     let _s = "foo\rbar";
 error: bare CR not allowed in raw string
   --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:22:19
    |
-LL |     let _s = r"bar␍foo";
+LL |     let _s = r"bar
foo";
    |                   ^
 
 error: unknown character escape: `\r`
   --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:25:19
    |
-LL |     let _s = "foo\␍bar";
+LL |     let _s = "foo\
bar";
    |                   ^ unknown character escape
    |
    = help: this is an isolated carriage return; consider checking your editor and version control settings
diff --git a/tests/ui/lexer/unterminated-comment.stderr b/tests/ui/lexer/unterminated-comment.stderr
index 6ab5441ee05ce..ea65bffd10368 100644
--- a/tests/ui/lexer/unterminated-comment.stderr
+++ b/tests/ui/lexer/unterminated-comment.stderr
@@ -2,7 +2,7 @@ error[E0758]: unterminated block comment
   --> $DIR/unterminated-comment.rs:1:1
    |
 LL | /*
-   | ^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lexer/unterminated-nested-comment.stderr b/tests/ui/lexer/unterminated-nested-comment.stderr
index 78b72ce1fe4a0..9117b689c94e3 100644
--- a/tests/ui/lexer/unterminated-nested-comment.stderr
+++ b/tests/ui/lexer/unterminated-nested-comment.stderr
@@ -12,7 +12,7 @@ LL | | /*
    | | |
    | | ...as last nested comment starts here, maybe you want to close this instead?
 LL | | */
-   | |_-^
+   | |_--^
    |   |
    |   ...and last nested comment terminates here.
 
diff --git a/tests/ui/lint/issue-104897.stderr b/tests/ui/lint/issue-104897.stderr
index 584902ee4c03c..1f3d40605f673 100644
--- a/tests/ui/lint/issue-104897.stderr
+++ b/tests/ui/lint/issue-104897.stderr
@@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-104897.rs:5:18
    |
 LL | fn f(){(print!(á
-   |       --      - ^
+   |       --      -  ^
    |       ||      |
    |       ||      unclosed delimiter
    |       |unclosed delimiter
diff --git a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr
index d9748843fd7a8..ad90aeda1d13b 100644
--- a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr
+++ b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr
@@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11
    |
 LL | fn a(){{{
-   |       ---^
+   |       --- ^
    |       |||
    |       ||unclosed delimiter
    |       |unclosed delimiter
diff --git a/tests/ui/parser/bad-char-literals.rs b/tests/ui/parser/bad-char-literals.rs
index c3d55d3f7e3bf..748b4a22253f5 100644
Binary files a/tests/ui/parser/bad-char-literals.rs and b/tests/ui/parser/bad-char-literals.rs differ
diff --git a/tests/ui/parser/bad-char-literals.stderr b/tests/ui/parser/bad-char-literals.stderr
index 1fb324a1b7e84..89253d7d4aacd 100644
--- a/tests/ui/parser/bad-char-literals.stderr
+++ b/tests/ui/parser/bad-char-literals.stderr
@@ -25,7 +25,7 @@ LL |     '\n';
 error: character constant must be escaped: `\r`
   --> $DIR/bad-char-literals.rs:15:6
    |
-LL |     '␍';
+LL |     '
';
    |      ^
    |
 help: escape the character
@@ -33,19 +33,8 @@ help: escape the character
 LL |     '\r';
    |      ++
 
-error: character literal may only contain one codepoint
-  --> $DIR/bad-char-literals.rs:18:5
-   |
-LL |     '-␀-';
-   |     ^^^^^
-   |
-help: if you meant to write a string literal, use double quotes
-   |
-LL |     "-␀-";
-   |     ~   ~
-
 error: character constant must be escaped: `\t`
-  --> $DIR/bad-char-literals.rs:21:6
+  --> $DIR/bad-char-literals.rs:18:6
    |
 LL |     '    ';
    |      ^^^^
@@ -55,5 +44,5 @@ help: escape the character
 LL |     '\t';
    |      ++
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/parser/brace-in-let-chain.stderr b/tests/ui/parser/brace-in-let-chain.stderr
index d76cb25ad8b84..7182d86d001d0 100644
--- a/tests/ui/parser/brace-in-let-chain.stderr
+++ b/tests/ui/parser/brace-in-let-chain.stderr
@@ -31,7 +31,7 @@ LL |             && let () = ()
 LL |     }
    |     - ...as it matches this but it has different indentation
 LL | }
-   |                                                     ^
+   |                                                      ^
 
 error: found a `{` in the middle of a let-chain
   --> $DIR/brace-in-let-chain.rs:14:24
diff --git a/tests/ui/parser/byte-string-literals.stderr b/tests/ui/parser/byte-string-literals.stderr
index 24e0eaac8fa91..655b6998e85ff 100644
--- a/tests/ui/parser/byte-string-literals.stderr
+++ b/tests/ui/parser/byte-string-literals.stderr
@@ -43,7 +43,7 @@ error[E0766]: unterminated double quote byte string
 LL |       b"a
    |  ______^
 LL | | }
-   | |_^
+   | |__^
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/parser/deli-ident-issue-1.stderr b/tests/ui/parser/deli-ident-issue-1.stderr
index d17913eb7ea40..78f5d7b63b954 100644
--- a/tests/ui/parser/deli-ident-issue-1.stderr
+++ b/tests/ui/parser/deli-ident-issue-1.stderr
@@ -11,7 +11,7 @@ LL |     }
    |     - ...as it matches this but it has different indentation
 ...
 LL | fn main() { }
-   |                                                                 ^
+   |                                                                  ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/issues/issue-103451.stderr b/tests/ui/parser/issues/issue-103451.stderr
index f078e556e2b16..7ad816e451eab 100644
--- a/tests/ui/parser/issues/issue-103451.stderr
+++ b/tests/ui/parser/issues/issue-103451.stderr
@@ -4,7 +4,7 @@ error: this file contains an unclosed delimiter
 LL | struct S {
    |          - unclosed delimiter
 LL |     x: [u8; R
-   |        -     ^
+   |        -      ^
    |        |
    |        unclosed delimiter
 
diff --git a/tests/ui/parser/issues/issue-104367.stderr b/tests/ui/parser/issues/issue-104367.stderr
index c067d12e2d96c..e6e76535761fb 100644
--- a/tests/ui/parser/issues/issue-104367.stderr
+++ b/tests/ui/parser/issues/issue-104367.stderr
@@ -20,7 +20,7 @@ LL |         #![cfg] {
 LL |             #![w,)
    |                  - missing open `(` for this delimiter
 LL |
-   |                                                                      ^
+   |                                                                       ^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/issues/issue-105209.stderr b/tests/ui/parser/issues/issue-105209.stderr
index 72017e4327de4..c75eafa18335e 100644
--- a/tests/ui/parser/issues/issue-105209.stderr
+++ b/tests/ui/parser/issues/issue-105209.stderr
@@ -16,7 +16,7 @@ LL | #![c={#![c[)x
    |   |  unclosed delimiter
    |   unclosed delimiter
 LL |
-   |                                                                   ^
+   |                                                                    ^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/issues/issue-107705.stderr b/tests/ui/parser/issues/issue-107705.stderr
index 10a47b799318c..2d0c3e0e675c7 100644
--- a/tests/ui/parser/issues/issue-107705.stderr
+++ b/tests/ui/parser/issues/issue-107705.stderr
@@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-107705.rs:3:67
    |
 LL | fn f() {a(b:&,
-   |        - - unclosed delimiter                                    ^
+   |        - - unclosed delimiter                                     ^
    |        |
    |        unclosed delimiter
 
diff --git a/tests/ui/parser/issues/issue-2354.stderr b/tests/ui/parser/issues/issue-2354.stderr
index 3e63473b6f45c..fd649a575c6c6 100644
--- a/tests/ui/parser/issues/issue-2354.stderr
+++ b/tests/ui/parser/issues/issue-2354.stderr
@@ -10,7 +10,7 @@ LL | }
    | - ...as it matches this but it has different indentation
 ...
 LL |
-   |                                                   ^
+   |                                                    ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/issues/issue-62546.stderr b/tests/ui/parser/issues/issue-62546.stderr
index 6435cb2b719f4..6889cb3b8e9d2 100644
--- a/tests/ui/parser/issues/issue-62546.stderr
+++ b/tests/ui/parser/issues/issue-62546.stderr
@@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-62546.rs:1:60
    |
 LL | pub t(#
-   |      - unclosed delimiter                                 ^
+   |      - unclosed delimiter                                  ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/issues/issue-62554.stderr b/tests/ui/parser/issues/issue-62554.stderr
index d4aaef1618139..37314dd39c7fd 100644
--- a/tests/ui/parser/issues/issue-62554.stderr
+++ b/tests/ui/parser/issues/issue-62554.stderr
@@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-62554.rs:5:89
    |
 LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-   |               -                       -         -                  -                  -^
+   |               -                       -         -                  -                  - ^
    |               |                       |         |                  |                  |
    |               |                       |         |                  |                  unclosed delimiter
    |               |                       |         |                  unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-62881.stderr b/tests/ui/parser/issues/issue-62881.stderr
index d8ae2cf090530..2165a81a0482d 100644
--- a/tests/ui/parser/issues/issue-62881.stderr
+++ b/tests/ui/parser/issues/issue-62881.stderr
@@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-62881.rs:3:96
    |
 LL | fn f() -> isize { fn f() -> isize {} pub f<
-   |                 - unclosed delimiter                                                          ^
+   |                 - unclosed delimiter                                                           ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/issues/issue-62894.stderr b/tests/ui/parser/issues/issue-62894.stderr
index 230319fc31e7e..870633fc96f85 100644
--- a/tests/ui/parser/issues/issue-62894.stderr
+++ b/tests/ui/parser/issues/issue-62894.stderr
@@ -8,7 +8,7 @@ LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
    |        unclosed delimiter
 LL |
 LL | fn main() {}
-   |             ^
+   |              ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/issues/issue-62973.stderr b/tests/ui/parser/issues/issue-62973.stderr
index 493183988e18b..14411a8cb7849 100644
--- a/tests/ui/parser/issues/issue-62973.stderr
+++ b/tests/ui/parser/issues/issue-62973.stderr
@@ -25,7 +25,7 @@ LL | fn p() { match s { v, E { [) {) }
    |        unclosed delimiter
 LL |
 LL |
-   | ^
+   |  ^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/parser/issues/issue-63116.stderr b/tests/ui/parser/issues/issue-63116.stderr
index e0f7dd176ceb3..27c94f337bdb8 100644
--- a/tests/ui/parser/issues/issue-63116.stderr
+++ b/tests/ui/parser/issues/issue-63116.stderr
@@ -10,7 +10,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-63116.rs:3:18
    |
 LL | impl W <s(f;Y(;]
-   |          -     -^
+   |          -     - ^
    |          |     |
    |          |     missing open `[` for this delimiter
    |          unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-63135.stderr b/tests/ui/parser/issues/issue-63135.stderr
index d6275901a5329..9204f561e965f 100644
--- a/tests/ui/parser/issues/issue-63135.stderr
+++ b/tests/ui/parser/issues/issue-63135.stderr
@@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-63135.rs:3:16
    |
 LL | fn i(n{...,f #
-   |     - -       ^
+   |     - -        ^
    |     | |
    |     | unclosed delimiter
    |     unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-66473.stderr b/tests/ui/parser/issues/issue-66473.stderr
index ba38c4fa1b7ad..0e8b0a5da2205 100644
Binary files a/tests/ui/parser/issues/issue-66473.stderr and b/tests/ui/parser/issues/issue-66473.stderr differ
diff --git a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
index b82b0f3255b55..9f631edf680c8 100644
--- a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
+++ b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
@@ -41,7 +41,7 @@ LL |         V = [Vec::new; { [0].len() ].len() as isize,
    |                                    - missing open `[` for this delimiter
 ...
 LL | fn main() {}
-   |                                                                ^
+   |                                                                 ^
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/parser/issues/issue-68629.stderr b/tests/ui/parser/issues/issue-68629.stderr
index f003f37817951..2562baa1c49c3 100644
Binary files a/tests/ui/parser/issues/issue-68629.stderr and b/tests/ui/parser/issues/issue-68629.stderr differ
diff --git a/tests/ui/parser/issues/issue-68730.stderr b/tests/ui/parser/issues/issue-68730.stderr
index 9bd98287db34a..5bca5bbebeacb 100644
Binary files a/tests/ui/parser/issues/issue-68730.stderr and b/tests/ui/parser/issues/issue-68730.stderr differ
diff --git a/tests/ui/parser/issues/issue-81804.stderr b/tests/ui/parser/issues/issue-81804.stderr
index 6caaaa792b196..de3b33ecd95c6 100644
--- a/tests/ui/parser/issues/issue-81804.stderr
+++ b/tests/ui/parser/issues/issue-81804.stderr
@@ -10,7 +10,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-81804.rs:6:11
    |
 LL | fn p([=(}
-   |     --   ^
+   |     --    ^
    |     ||
    |     |unclosed delimiter
    |     unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-81827.stderr b/tests/ui/parser/issues/issue-81827.stderr
index d12c74b4a3420..63d135f73e69f 100644
--- a/tests/ui/parser/issues/issue-81827.stderr
+++ b/tests/ui/parser/issues/issue-81827.stderr
@@ -11,7 +11,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-81827.rs:10:27
    |
 LL | fn r()->i{0|{#[cfg(r(0{]0
-   |          -  -          - ^
+   |          -  -          -  ^
    |          |  |          |
    |          |  |          missing open `[` for this delimiter
    |          |  unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-84104.stderr b/tests/ui/parser/issues/issue-84104.stderr
index b9b14c081a985..e866d39226751 100644
--- a/tests/ui/parser/issues/issue-84104.stderr
+++ b/tests/ui/parser/issues/issue-84104.stderr
@@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-84104.rs:2:13
    |
 LL | #[i=i::<ښܖ<
-   |  -         ^
+   |  -          ^
    |  |
    |  unclosed delimiter
 
diff --git a/tests/ui/parser/issues/issue-84148-2.stderr b/tests/ui/parser/issues/issue-84148-2.stderr
index b30f3d9114c1d..d9b6b336a2ce8 100644
--- a/tests/ui/parser/issues/issue-84148-2.stderr
+++ b/tests/ui/parser/issues/issue-84148-2.stderr
@@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-84148-2.rs:2:16
    |
 LL | fn f(t:for<>t?
-   |     -         ^
+   |     -          ^
    |     |
    |     unclosed delimiter
 
diff --git a/tests/ui/parser/issues/issue-88770.stderr b/tests/ui/parser/issues/issue-88770.stderr
index 5b54072d009fb..60ef025fa8bfd 100644
--- a/tests/ui/parser/issues/issue-88770.stderr
+++ b/tests/ui/parser/issues/issue-88770.stderr
@@ -8,7 +8,7 @@ LL | fn m(){print!("",(c for&g
    |       unclosed delimiter
 ...
 LL | e
-   |  ^
+   |   ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
index 39144246be24a..97aac661d4658 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
@@ -5,7 +5,7 @@ LL | impl T for () {
    |               - unclosed delimiter
 ...
 LL |
-   |                                                   ^
+   |                                                    ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
index 603aee02ad6b0..f70dac443e55f 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
@@ -5,7 +5,7 @@ LL | pub(crate) struct Bar<T> {
    |                          - unclosed delimiter
 ...
 LL | fn main() {}
-   |                                                                ^
+   |                                                                 ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
index a2fb698c80f65..a565ad49b221c 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
@@ -5,7 +5,7 @@ LL | trait T {
    |         - unclosed delimiter
 ...
 LL | fn main() {}
-   |                                                                ^
+   |                                                                 ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/parser-ice-ed2021-await-105210.stderr b/tests/ui/parser/parser-ice-ed2021-await-105210.stderr
index 29abab2608e94..fc54476c22048 100644
--- a/tests/ui/parser/parser-ice-ed2021-await-105210.stderr
+++ b/tests/ui/parser/parser-ice-ed2021-await-105210.stderr
@@ -28,7 +28,7 @@ LL |  (( h (const {( default ( await ( await (    (move {await((((}}
    |  unclosed delimiter
 ...
 LL |
-   |                                                   ^
+   |                                                    ^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/parser/parser-recovery-1.stderr b/tests/ui/parser/parser-recovery-1.stderr
index 4ed40d7532612..8162db3d8e5d6 100644
--- a/tests/ui/parser/parser-recovery-1.stderr
+++ b/tests/ui/parser/parser-recovery-1.stderr
@@ -10,7 +10,7 @@ LL | }
    | - ...as it matches this but it has different indentation
 ...
 LL | }
-   |                                                     ^
+   |                                                      ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/raw/raw-byte-string-literals.stderr b/tests/ui/parser/raw/raw-byte-string-literals.stderr
index a20ce845c3268..a2f27d1ed70ae 100644
--- a/tests/ui/parser/raw/raw-byte-string-literals.stderr
+++ b/tests/ui/parser/raw/raw-byte-string-literals.stderr
@@ -1,7 +1,7 @@
 error: bare CR not allowed in raw string
   --> $DIR/raw-byte-string-literals.rs:4:9
    |
-LL |     br"a␍";
+LL |     br"a
";
    |         ^
 
 error: non-ASCII character in raw byte string literal
diff --git a/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr b/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr
index e235a15838493..07066fc22e6cd 100644
--- a/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr
+++ b/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr
@@ -1,20 +1,20 @@
 error: bare CR not allowed in doc-comment
   --> $DIR/several-carriage-returns-in-doc-comment.rs:6:12
    |
-LL | /// This do␍c comment contains ␍three isolated `\r`␍ symbols
+LL | /// This do
c comment contains 
three isolated `\r`
 symbols
    |            ^
 
 error: bare CR not allowed in doc-comment
   --> $DIR/several-carriage-returns-in-doc-comment.rs:6:32
    |
-LL | /// This do␍c comment contains ␍three isolated `\r`␍ symbols
-   |                                ^
+LL | /// This do
c comment contains 
three isolated `\r`
 symbols
+   |                               ^
 
 error: bare CR not allowed in doc-comment
   --> $DIR/several-carriage-returns-in-doc-comment.rs:6:52
    |
-LL | /// This do␍c comment contains ␍three isolated `\r`␍ symbols
-   |                                                    ^
+LL | /// This do
c comment contains 
three isolated `\r`
 symbols
+   |                                                  ^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/parser/trailing-carriage-return-in-string.stderr b/tests/ui/parser/trailing-carriage-return-in-string.stderr
index c5949432af893..fa2677921b32d 100644
--- a/tests/ui/parser/trailing-carriage-return-in-string.stderr
+++ b/tests/ui/parser/trailing-carriage-return-in-string.stderr
@@ -1,7 +1,7 @@
 error: unknown character escape: `\r`
   --> $DIR/trailing-carriage-return-in-string.rs:10:25
    |
-LL |     let bad = "This is \␍ a test";
+LL |     let bad = "This is \
 a test";
    |                         ^ unknown character escape
    |
    = help: this is an isolated carriage return; consider checking your editor and version control settings
diff --git a/tests/ui/parser/unbalanced-doublequote.stderr b/tests/ui/parser/unbalanced-doublequote.stderr
index 9fdad87a86cf1..d40b982da7c39 100644
--- a/tests/ui/parser/unbalanced-doublequote.stderr
+++ b/tests/ui/parser/unbalanced-doublequote.stderr
@@ -3,7 +3,7 @@ error[E0765]: unterminated double quote string
    |
 LL | /     "
 LL | | }
-   | |_^
+   | |__^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/unclosed-braces.stderr b/tests/ui/parser/unclosed-braces.stderr
index 74ac66af528db..acd92ac792597 100644
--- a/tests/ui/parser/unclosed-braces.stderr
+++ b/tests/ui/parser/unclosed-braces.stderr
@@ -11,7 +11,7 @@ LL |     }
    |     - ...as it matches this but it has different indentation
 ...
 LL |
-   |                                                   ^
+   |                                                    ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/unicode-control-codepoints.stderr b/tests/ui/parser/unicode-control-codepoints.stderr
index 28de4ae72abbd..fc071a9419142 100644
--- a/tests/ui/parser/unicode-control-codepoints.stderr
+++ b/tests/ui/parser/unicode-control-codepoints.stderr
@@ -17,78 +17,78 @@ LL |     println!("{:?}", b"us\u{202B}e\u{202A}r");
 error: non-ASCII character in byte string literal
   --> $DIR/unicode-control-codepoints.rs:16:26
    |
-LL |     println!("{:?}", b"/*� } �if isAdmin� � begin admins only ");
+LL |     println!("{:?}", b"/* } if isAdmin  begin admins only ");
    |                          ^ must be ASCII but is '\u{202e}'
    |
 help: if you meant to use the UTF-8 encoding of '\u{202e}', use \xHH escapes
    |
-LL |     println!("{:?}", b"/*\xE2\x80\xAE } �if isAdmin� � begin admins only ");
+LL |     println!("{:?}", b"/*\xE2\x80\xAE } if isAdmin  begin admins only ");
    |                          ~~~~~~~~~~~~
 
 error: non-ASCII character in byte string literal
   --> $DIR/unicode-control-codepoints.rs:16:30
    |
-LL |     println!("{:?}", b"/*� } �if isAdmin� � begin admins only ");
-   |                              ^ must be ASCII but is '\u{2066}'
+LL |     println!("{:?}", b"/* } if isAdmin  begin admins only ");
+   |                             ^ must be ASCII but is '\u{2066}'
    |
 help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes
    |
-LL |     println!("{:?}", b"/*� } \xE2\x81\xA6if isAdmin� � begin admins only ");
-   |                              ~~~~~~~~~~~~
+LL |     println!("{:?}", b"/* } \xE2\x81\xA6if isAdmin  begin admins only ");
+   |                             ~~~~~~~~~~~~
 
 error: non-ASCII character in byte string literal
   --> $DIR/unicode-control-codepoints.rs:16:41
    |
-LL |     println!("{:?}", b"/*� } �if isAdmin� � begin admins only ");
-   |                                         ^ must be ASCII but is '\u{2069}'
+LL |     println!("{:?}", b"/* } if isAdmin  begin admins only ");
+   |                                       ^ must be ASCII but is '\u{2069}'
    |
 help: if you meant to use the UTF-8 encoding of '\u{2069}', use \xHH escapes
    |
-LL |     println!("{:?}", b"/*� } �if isAdmin\xE2\x81\xA9 � begin admins only ");
-   |                                         ~~~~~~~~~~~~
+LL |     println!("{:?}", b"/* } if isAdmin\xE2\x81\xA9  begin admins only ");
+   |                                       ~~~~~~~~~~~~
 
 error: non-ASCII character in byte string literal
   --> $DIR/unicode-control-codepoints.rs:16:43
    |
-LL |     println!("{:?}", b"/*� } �if isAdmin� � begin admins only ");
-   |                                           ^ must be ASCII but is '\u{2066}'
+LL |     println!("{:?}", b"/* } if isAdmin  begin admins only ");
+   |                                        ^ must be ASCII but is '\u{2066}'
    |
 help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes
    |
-LL |     println!("{:?}", b"/*� } �if isAdmin� \xE2\x81\xA6 begin admins only ");
-   |                                           ~~~~~~~~~~~~
+LL |     println!("{:?}", b"/* } if isAdmin \xE2\x81\xA6 begin admins only ");
+   |                                        ~~~~~~~~~~~~
 
 error: non-ASCII character in raw byte string literal
   --> $DIR/unicode-control-codepoints.rs:21:29
    |
-LL |     println!("{:?}", br##"/*� } �if isAdmin� � begin admins only "##);
+LL |     println!("{:?}", br##"/* } if isAdmin  begin admins only "##);
    |                             ^ must be ASCII but is '\u{202e}'
 
 error: non-ASCII character in raw byte string literal
   --> $DIR/unicode-control-codepoints.rs:21:33
    |
-LL |     println!("{:?}", br##"/*� } �if isAdmin� � begin admins only "##);
-   |                                 ^ must be ASCII but is '\u{2066}'
+LL |     println!("{:?}", br##"/* } if isAdmin  begin admins only "##);
+   |                                ^ must be ASCII but is '\u{2066}'
 
 error: non-ASCII character in raw byte string literal
   --> $DIR/unicode-control-codepoints.rs:21:44
    |
-LL |     println!("{:?}", br##"/*� } �if isAdmin� � begin admins only "##);
-   |                                            ^ must be ASCII but is '\u{2069}'
+LL |     println!("{:?}", br##"/* } if isAdmin  begin admins only "##);
+   |                                          ^ must be ASCII but is '\u{2069}'
 
 error: non-ASCII character in raw byte string literal
   --> $DIR/unicode-control-codepoints.rs:21:46
    |
-LL |     println!("{:?}", br##"/*� } �if isAdmin� � begin admins only "##);
-   |                                              ^ must be ASCII but is '\u{2066}'
+LL |     println!("{:?}", br##"/* } if isAdmin  begin admins only "##);
+   |                                           ^ must be ASCII but is '\u{2066}'
 
 error: unicode codepoint changing visible direction of text present in comment
   --> $DIR/unicode-control-codepoints.rs:2:5
    |
-LL |     // if access_level != "us�e�r" { // Check if admin
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^-^-^^^^^^^^^^^^^^^^^^^^^^
-   |     |                        | |
-   |     |                        | '\u{202a}'
+LL |     // if access_level != "user" { // Check if admin
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^
+   |     |                        ||
+   |     |                        |'\u{202a}'
    |     |                        '\u{202b}'
    |     this comment contains invisible unicode text flow control codepoints
    |
@@ -99,12 +99,12 @@ LL |     // if access_level != "us�e�r" { // Check if admin
 error: unicode codepoint changing visible direction of text present in comment
   --> $DIR/unicode-control-codepoints.rs:30:1
    |
-LL | //"/*� } �if isAdmin� � begin admins only */"
-   | ^^^^^-^^^-^^^^^^^^^^-^-^^^^^^^^^^^^^^^^^^^^^^
-   | |    |   |          | |
-   | |    |   |          | '\u{2066}'
-   | |    |   |          '\u{2069}'
-   | |    |   '\u{2066}'
+LL | //"/* } if isAdmin  begin admins only */"
+   | ^^^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^
+   | |    |  |         ||
+   | |    |  |         |'\u{2066}'
+   | |    |  |         '\u{2069}'
+   | |    |  '\u{2066}'
    | |    '\u{202e}'
    | this comment contains invisible unicode text flow control codepoints
    |
@@ -114,12 +114,12 @@ LL | //"/*� } �if isAdmin� � begin admins only */"
 error: unicode codepoint changing visible direction of text present in literal
   --> $DIR/unicode-control-codepoints.rs:11:22
    |
-LL |     println!("{:?}", "/*� } �if isAdmin� � begin admins only ");
-   |                      ^^^-^^^-^^^^^^^^^^-^-^^^^^^^^^^^^^^^^^^^^
-   |                      |  |   |          | |
-   |                      |  |   |          | '\u{2066}'
-   |                      |  |   |          '\u{2069}'
-   |                      |  |   '\u{2066}'
+LL |     println!("{:?}", "/* } if isAdmin  begin admins only ");
+   |                      ^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^
+   |                      |  |  |         ||
+   |                      |  |  |         |'\u{2066}'
+   |                      |  |  |         '\u{2069}'
+   |                      |  |  '\u{2066}'
    |                      |  '\u{202e}'
    |                      this literal contains invisible unicode text flow control codepoints
    |
@@ -134,12 +134,12 @@ LL |     println!("{:?}", "/*\u{202e} } \u{2066}if isAdmin\u{2069} \u{2066} begi
 error: unicode codepoint changing visible direction of text present in literal
   --> $DIR/unicode-control-codepoints.rs:14:22
    |
-LL |     println!("{:?}", r##"/*� } �if isAdmin� � begin admins only "##);
-   |                      ^^^^^^-^^^-^^^^^^^^^^-^-^^^^^^^^^^^^^^^^^^^^^^
-   |                      |     |   |          | |
-   |                      |     |   |          | '\u{2066}'
-   |                      |     |   |          '\u{2069}'
-   |                      |     |   '\u{2066}'
+LL |     println!("{:?}", r##"/* } if isAdmin  begin admins only "##);
+   |                      ^^^^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^
+   |                      |     |  |         ||
+   |                      |     |  |         |'\u{2066}'
+   |                      |     |  |         '\u{2069}'
+   |                      |     |  '\u{2066}'
    |                      |     '\u{202e}'
    |                      this literal contains invisible unicode text flow control codepoints
    |
@@ -153,8 +153,8 @@ LL |     println!("{:?}", r##"/*\u{202e} } \u{2066}if isAdmin\u{2069} \u{2066} b
 error: unicode codepoint changing visible direction of text present in literal
   --> $DIR/unicode-control-codepoints.rs:26:22
    |
-LL |     println!("{:?}", '�');
-   |                      ^-^
+LL |     println!("{:?}", '');
+   |                      ^-
    |                      ||
    |                      |'\u{202e}'
    |                      this literal contains an invisible unicode text flow control codepoint
@@ -169,8 +169,8 @@ LL |     println!("{:?}", '\u{202e}');
 error: unicode codepoint changing visible direction of text present in doc comment
   --> $DIR/unicode-control-codepoints.rs:33:1
    |
-LL | /**  '�'); */fn foo() {}
-   | ^^^^^^^^^^^^^ this doc comment contains an invisible unicode text flow control codepoint
+LL | /**  ''); */fn foo() {}
+   | ^^^^^^^^^^^^ this doc comment contains an invisible unicode text flow control codepoint
    |
    = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
    = note: if their presence wasn't intentional, you can remove them
@@ -181,8 +181,8 @@ error: unicode codepoint changing visible direction of text present in doc comme
    |
 LL | / /**
 LL | |  *
-LL | |  *  '�'); */fn bar() {}
-   | |____________^ this doc comment contains an invisible unicode text flow control codepoint
+LL | |  *  ''); */fn bar() {}
+   | |___________^ this doc comment contains an invisible unicode text flow control codepoint
    |
    = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
    = note: if their presence wasn't intentional, you can remove them
diff --git a/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr b/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr
index 192f5324935f6..c6960892b2bc8 100644
--- a/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr
+++ b/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr
@@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/unmatched-delimiter-at-end-of-file.rs:11:63
    |
 LL | fn foo() {
-   |          - unclosed delimiter                                ^
+   |          - unclosed delimiter                                 ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/use-unclosed-brace.stderr b/tests/ui/parser/use-unclosed-brace.stderr
index 1e62a0a06a36b..6e624cb913163 100644
--- a/tests/ui/parser/use-unclosed-brace.stderr
+++ b/tests/ui/parser/use-unclosed-brace.stderr
@@ -5,7 +5,7 @@ LL | use foo::{bar, baz;
    |          - unclosed delimiter
 ...
 LL | fn main() {}
-   |             ^
+   |              ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/utf16-be-without-bom.stderr b/tests/ui/parser/utf16-be-without-bom.stderr
index 55ebf7aacd237..c041f3ecf53b2 100644
Binary files a/tests/ui/parser/utf16-be-without-bom.stderr and b/tests/ui/parser/utf16-be-without-bom.stderr differ
diff --git a/tests/ui/parser/utf16-le-without-bom.stderr b/tests/ui/parser/utf16-le-without-bom.stderr
index ad272a70f0627..cc2220441ac10 100644
Binary files a/tests/ui/parser/utf16-le-without-bom.stderr and b/tests/ui/parser/utf16-le-without-bom.stderr differ
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr
index 90cca83d1c1f5..0c5a06e68b89f 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr
@@ -1,6 +1,6 @@
 error: Dlltool could not create import library with $DLLTOOL -d $DEF_FILE -D foo.dll -l $LIB_FILE $TARGET_MACHINE $ASM_FLAGS --no-leading-underscore $TEMP_PREFIX:
        
-       $DLLTOOL: Syntax error in def file $DEF_FILE:1␍
+       $DLLTOOL: Syntax error in def file $DEF_FILE:1
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr
index 13cbd8370db64..a05dea3ff07e6 100644
Binary files a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr and b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr differ
diff --git a/tests/ui/rustdoc/unterminated-doc-comment.stderr b/tests/ui/rustdoc/unterminated-doc-comment.stderr
index f0b691333dc93..2d96c606b1636 100644
--- a/tests/ui/rustdoc/unterminated-doc-comment.stderr
+++ b/tests/ui/rustdoc/unterminated-doc-comment.stderr
@@ -2,7 +2,7 @@ error[E0758]: unterminated block doc-comment
   --> $DIR/unterminated-doc-comment.rs:1:1
    |
 LL | /*!
-   | ^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
index c8cce16241617..004a057bbcdaf 100644
--- a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
+++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
@@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:12:85
    |
 LL | trait C{async fn new(val: T) {}
-   |        - unclosed delimiter                                                        ^
+   |        - unclosed delimiter                                                         ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/str/str-escape.stderr b/tests/ui/str/str-escape.stderr
index 4c8ee6bc013ef..c4aee2a110a5b 100644
--- a/tests/ui/str/str-escape.stderr
+++ b/tests/ui/str/str-escape.stderr
@@ -22,9 +22,9 @@ warning: whitespace symbol '\u{c}' is not skipped
    |
 LL |       let s = b"a\
    |  ________________^
-LL | |     ␌b";
-   | |     ^ whitespace symbol '\u{c}' is not skipped
-   | |_____|
+LL | |     b";
+   | |    ^- whitespace symbol '\u{c}' is not skipped
+   | |____|
    |
 
 warning: 3 warnings emitted
diff --git a/tests/ui/suggestions/issue-94171.stderr b/tests/ui/suggestions/issue-94171.stderr
index 3d73ee1d27a06..b3440e46e8acd 100644
--- a/tests/ui/suggestions/issue-94171.stderr
+++ b/tests/ui/suggestions/issue-94171.stderr
@@ -30,7 +30,7 @@ LL | (; {`
    | unclosed delimiter
 ...
 LL |
-   |                                                   ^
+   |                                                    ^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/typeck/issue-91334.stderr b/tests/ui/typeck/issue-91334.stderr
index 01e34919ce67d..7cb30eea530c6 100644
--- a/tests/ui/typeck/issue-91334.stderr
+++ b/tests/ui/typeck/issue-91334.stderr
@@ -11,7 +11,7 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-91334.rs:7:23
    |
 LL | fn f(){||yield(((){),
-   |       -       -    - ^
+   |       -       -    -  ^
    |       |       |    |
    |       |       |    missing open `(` for this delimiter
    |       |       unclosed delimiter