about summary refs log tree commit diff
path: root/compiler/rustc_errors/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_errors/src')
-rw-r--r--compiler/rustc_errors/src/emitter.rs25
-rw-r--r--compiler/rustc_errors/src/styled_buffer.rs27
2 files changed, 23 insertions, 29 deletions
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 32104e6f00d..00882bb287a 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -644,6 +644,8 @@ impl EmitterWriter {
         code_offset: usize,
         margin: Margin,
     ) {
+        // Tabs are assumed to have been replaced by spaces in calling code.
+        assert!(!source_string.contains('\t'));
         let line_len = source_string.len();
         // Create the source line we will highlight.
         let left = margin.left(line_len);
@@ -707,7 +709,7 @@ impl EmitterWriter {
         }
 
         let source_string = match file.get_line(line.line_index - 1) {
-            Some(s) => s,
+            Some(s) => replace_tabs(&*s),
             None => return Vec::new(),
         };
 
@@ -1376,8 +1378,17 @@ impl EmitterWriter {
                     let file = annotated_file.file.clone();
                     let line = &annotated_file.lines[line_idx];
                     if let Some(source_string) = file.get_line(line.line_index - 1) {
-                        let leading_whitespace =
-                            source_string.chars().take_while(|c| c.is_whitespace()).count();
+                        let leading_whitespace = source_string
+                            .chars()
+                            .take_while(|c| c.is_whitespace())
+                            .map(|c| {
+                                match c {
+                                    // Tabs are displayed as 4 spaces
+                                    '\t' => 4,
+                                    _ => 1,
+                                }
+                            })
+                            .sum();
                         if source_string.chars().any(|c| !c.is_whitespace()) {
                             whitespace_margin = min(whitespace_margin, leading_whitespace);
                         }
@@ -1502,7 +1513,7 @@ impl EmitterWriter {
 
                             self.draw_line(
                                 &mut buffer,
-                                &unannotated_line,
+                                &replace_tabs(&unannotated_line),
                                 annotated_file.lines[line_idx + 1].line_index - 1,
                                 last_buffer_line_num,
                                 width_offset,
@@ -1598,7 +1609,7 @@ impl EmitterWriter {
                 );
                 // print the suggestion
                 draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
-                buffer.append(row_num, line, Style::NoStyle);
+                buffer.append(row_num, &replace_tabs(line), Style::NoStyle);
                 row_num += 1;
             }
 
@@ -1930,6 +1941,10 @@ impl FileWithAnnotatedLines {
     }
 }
 
+fn replace_tabs(str: &str) -> String {
+    str.replace('\t', "    ")
+}
+
 fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
     buffer.puts(line, col, "| ", Style::LineNumber);
 }
diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs
index f2d255d7d95..a4dd0f391bd 100644
--- a/compiler/rustc_errors/src/styled_buffer.rs
+++ b/compiler/rustc_errors/src/styled_buffer.rs
@@ -13,34 +13,13 @@ impl StyledBuffer {
         StyledBuffer { text: vec![], styles: vec![] }
     }
 
-    fn replace_tabs(&mut self) {
-        for (line_pos, line) in self.text.iter_mut().enumerate() {
-            let mut tab_pos = vec![];
-            for (pos, c) in line.iter().enumerate() {
-                if *c == '\t' {
-                    tab_pos.push(pos);
-                }
-            }
-            // start with the tabs at the end of the line to replace them with 4 space chars
-            for pos in tab_pos.iter().rev() {
-                assert_eq!(line.remove(*pos), '\t');
-                // fix the position of the style to match up after replacing the tabs
-                let s = self.styles[line_pos].remove(*pos);
-                for _ in 0..4 {
-                    line.insert(*pos, ' ');
-                    self.styles[line_pos].insert(*pos, s);
-                }
-            }
-        }
-    }
+    pub fn render(&self) -> Vec<Vec<StyledString>> {
+        // Tabs are assumed to have been replaced by spaces in calling code.
+        assert!(self.text.iter().all(|r| !r.contains(&'\t')));
 
-    pub fn render(&mut self) -> Vec<Vec<StyledString>> {
         let mut output: Vec<Vec<StyledString>> = vec![];
         let mut styled_vec: Vec<StyledString> = vec![];
 
-        // before we render, replace tabs with spaces
-        self.replace_tabs();
-
         for (row, row_style) in self.text.iter().zip(&self.styles) {
             let mut current_style = Style::NoStyle;
             let mut current_text = String::new();