Skip to content

Commit

Permalink
Teach diagnostics to have correctly padded lists
Browse files Browse the repository at this point in the history
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()
```
  • Loading branch information
estebank committed Jan 8, 2017
1 parent 7e38a89 commit 43b10fa
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 17 deletions.
18 changes: 18 additions & 0 deletions src/librustc_errors/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub struct SubDiagnostic {
pub message: String,
pub span: MultiSpan,
pub render_span: Option<RenderSpan>,
pub list: Vec<String>,
}

impl Diagnostic {
Expand Down Expand Up @@ -132,6 +133,11 @@ impl Diagnostic {
self
}

pub fn help_with_list(&mut self , msg: &str, list: Vec<String>) -> &mut Self {
self.sub_with_list(Level::Help, msg, MultiSpan::new(), None, list);
self
}

pub fn span_help<S: Into<MultiSpan>>(&mut self,
sp: S,
msg: &str)
Expand Down Expand Up @@ -191,11 +197,23 @@ impl Diagnostic {
message: &str,
span: MultiSpan,
render_span: Option<RenderSpan>) {
self.sub_with_list(level, message, span, render_span, vec![]);
}

/// Convenience function for internal use, clients should use one of the
/// public methods above.
fn sub_with_list(&mut self,
level: Level,
message: &str,
span: MultiSpan,
render_span: Option<RenderSpan>,
list: Vec<String>) {
let sub = SubDiagnostic {
level: level,
message: message.to_owned(),
span: span,
render_span: render_span,
list: list,
};
self.children.push(sub);
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_errors/diagnostic_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ impl<'a> DiagnosticBuilder<'a> {
forward!(pub fn warn(&mut self, msg: &str) -> &mut Self);
forward!(pub fn span_warn<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self);
forward!(pub fn help(&mut self , msg: &str) -> &mut Self);
forward!(pub fn help_with_list(&mut self , msg: &str, list: Vec<String>) -> &mut Self);
forward!(pub fn span_help<S: Into<MultiSpan>>(&mut self,
sp: S,
msg: &str)
Expand Down
19 changes: 17 additions & 2 deletions src/librustc_errors/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,7 @@ impl EmitterWriter {
.to_string(),
span: MultiSpan::new(),
render_span: None,
list: vec![],
});
}
}
Expand Down Expand Up @@ -923,14 +924,28 @@ impl EmitterWriter {
}
},
None => {
let msg = if child.list.len() == 0 {
child.message.to_owned()
} else {
format!("{}\n{}",
&child.message,
&child.list.iter().map(|item| {
format!("{} - {}",
(0..max_line_num_len)
.map(|_| " ")
.collect::<String>(),
item)
}).collect::<Vec<String>>()
.join("\n"))
};
match self.emit_message_default(&child.span,
&child.message,
&msg,
&None,
&child.level,
max_line_num_len,
true) {
Err(e) => panic!("failed to emit error: {}", e),
_ => ()
_ => (),
}
}
}
Expand Down
10 changes: 4 additions & 6 deletions src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
ast::DUMMY_NODE_ID);
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)));
err.help_with_list("here are some functions which might fulfill your needs:",
self.get_best_match(&suggestions));
};
err.emit();
}
Expand All @@ -88,15 +87,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))
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/resolve/token-error-correct-3.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

12 changes: 6 additions & 6 deletions src/test/ui/span/coerce-suggestions.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 43b10fa

Please sign in to comment.