about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-01-11 05:27:11 +0000
committerbors <bors@rust-lang.org>2017-01-11 05:27:11 +0000
commite57f061be20666eb0506f6f41551c798bbb38b60 (patch)
treecd8e01c09388b85eb7315fc9cde960cac96ddb51
parente4fee525e04838dabc82beed5ae1a06051be53fd (diff)
parent04e4a60b45ec4debd20be2327cb6859271502c05 (diff)
downloadrust-e57f061be20666eb0506f6f41551c798bbb38b60.tar.gz
rust-e57f061be20666eb0506f6f41551c798bbb38b60.zip
Auto merge of #38916 - estebank:pad-suggestion-list, r=nikomatsakis
Teach diagnostics to correct margin of multiline messages

Make the suggestion list have a correct padding:

```
error[E0308]: mismatched types
 --> file.rs:3:20
  |
3 |     let x: usize = "";
  |                    ^^ expected usize, found reference
  |
  = note: expected type `usize`
  = note:    found type `&'static str`
  = help: here are some functions which might fulfill your needs:
          - .len()
          - .foo()
          - .bar()
```
-rw-r--r--src/librustc_errors/emitter.rs44
-rw-r--r--src/librustc_typeck/check/demand.rs11
-rw-r--r--src/test/ui/resolve/token-error-correct-3.stderr6
-rw-r--r--src/test/ui/span/coerce-suggestions.stderr12
4 files changed, 55 insertions, 18 deletions
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 808fe504b95..77c6c368364 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -703,6 +703,40 @@ impl EmitterWriter {
         }
     }
 
+    /// Add a left margin to every line but the first, given a padding length and the label being
+    /// displayed.
+    fn msg_with_padding(&self, msg: &str, padding: usize, label: &str) -> String {
+        // The extra 5 ` ` is padding that's always needed to align to the `note: `:
+        //
+        //   error: message
+        //     --> file.rs:13:20
+        //      |
+        //   13 |     <CODE>
+        //      |      ^^^^
+        //      |
+        //      = note: multiline
+        //              message
+        //   ++^^^----xx
+        //    |  |   | |
+        //    |  |   | magic `2`
+        //    |  |   length of label
+        //    |  magic `3`
+        //    `max_line_num_len`
+        let padding = (0..padding + label.len() + 5)
+            .map(|_| " ")
+            .collect::<String>();
+
+        msg.split('\n').enumerate().fold("".to_owned(), |mut acc, x| {
+            if x.0 != 0 {
+                acc.push_str("\n");
+                // Align every line with first one.
+                acc.push_str(&padding);
+            }
+            acc.push_str(&x.1);
+            acc
+        })
+    }
+
     fn emit_message_default(&mut self,
                             msp: &MultiSpan,
                             msg: &str,
@@ -721,7 +755,9 @@ impl EmitterWriter {
             draw_note_separator(&mut buffer, 0, max_line_num_len + 1);
             buffer.append(0, &level.to_string(), Style::HeaderMsg);
             buffer.append(0, ": ", Style::NoStyle);
-            buffer.append(0, msg, Style::NoStyle);
+
+            let message = self.msg_with_padding(msg, max_line_num_len, "note");
+            buffer.append(0, &message, Style::NoStyle);
         } else {
             buffer.append(0, &level.to_string(), Style::Level(level.clone()));
             match code {
@@ -854,7 +890,9 @@ impl EmitterWriter {
 
             buffer.append(0, &level.to_string(), Style::Level(level.clone()));
             buffer.append(0, ": ", Style::HeaderMsg);
-            buffer.append(0, msg, Style::HeaderMsg);
+
+            let message = self.msg_with_padding(msg, max_line_num_len, "suggestion");
+            buffer.append(0, &message, Style::HeaderMsg);
 
             let lines = cm.span_to_lines(primary_span).unwrap();
 
@@ -930,7 +968,7 @@ impl EmitterWriter {
                                                             max_line_num_len,
                                                             true) {
                                 Err(e) => panic!("failed to emit error: {}", e),
-                                _ => ()
+                                _ => (),
                             }
                         }
                     }
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 393d9341a08..3bc3d1a2c97 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -71,15 +71,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
             if suggestions.len() > 0 {
                 err.help(&format!("here are some functions which \
-                                   might fulfill your needs:\n - {}",
-                                  self.get_best_match(&suggestions)));
+                                   might fulfill your needs:\n{}",
+                                  self.get_best_match(&suggestions).join("\n")));
             };
             err.emit();
         }
     }
 
     fn format_method_suggestion(&self, method: &AssociatedItem) -> String {
-        format!(".{}({})",
+        format!("- .{}({})",
                 method.name,
                 if self.has_no_input_arg(method) {
                     ""
@@ -88,15 +88,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 })
     }
 
-    fn display_suggested_methods(&self, methods: &[AssociatedItem]) -> String {
+    fn display_suggested_methods(&self, methods: &[AssociatedItem]) -> Vec<String> {
         methods.iter()
                .take(5)
                .map(|method| self.format_method_suggestion(&*method))
                .collect::<Vec<String>>()
-               .join("\n - ")
     }
 
-    fn get_best_match(&self, methods: &[AssociatedItem]) -> String {
+    fn get_best_match(&self, methods: &[AssociatedItem]) -> Vec<String> {
         let no_argument_methods: Vec<_> =
             methods.iter()
                    .filter(|ref x| self.has_no_input_arg(&*x))
diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr
index 0b15c23909c..bb6f310fec8 100644
--- a/src/test/ui/resolve/token-error-correct-3.stderr
+++ b/src/test/ui/resolve/token-error-correct-3.stderr
@@ -37,9 +37,9 @@ error[E0308]: mismatched types
    = note: expected type `()`
    = note:    found type `std::result::Result<bool, std::io::Error>`
    = help: here are some functions which might fulfill your needs:
- - .unwrap()
- - .unwrap_err()
- - .unwrap_or_default()
+           - .unwrap()
+           - .unwrap_err()
+           - .unwrap_or_default()
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr
index e3164661507..ed1bcd318a4 100644
--- a/src/test/ui/span/coerce-suggestions.stderr
+++ b/src/test/ui/span/coerce-suggestions.stderr
@@ -7,8 +7,8 @@ error[E0308]: mismatched types
    = note: expected type `usize`
    = note:    found type `std::string::String`
    = help: here are some functions which might fulfill your needs:
- - .capacity()
- - .len()
+           - .capacity()
+           - .len()
 
 error[E0308]: mismatched types
   --> $DIR/coerce-suggestions.rs:23:19
@@ -19,10 +19,10 @@ error[E0308]: mismatched types
    = note: expected type `&str`
    = note:    found type `std::string::String`
    = help: here are some functions which might fulfill your needs:
- - .as_str()
- - .trim()
- - .trim_left()
- - .trim_right()
+           - .as_str()
+           - .trim()
+           - .trim_left()
+           - .trim_right()
 
 error[E0308]: mismatched types
   --> $DIR/coerce-suggestions.rs:30:10