diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 730ca8f9e2e44..73a8343eafc45 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -32,6 +32,7 @@ pub struct SubDiagnostic { pub message: String, pub span: MultiSpan, pub render_span: Option, + pub list: Vec, } impl Diagnostic { @@ -132,6 +133,11 @@ impl Diagnostic { self } + pub fn help_with_list(&mut self , msg: &str, list: Vec) -> &mut Self { + self.sub_with_list(Level::Help, msg, MultiSpan::new(), None, list); + self + } + pub fn span_help>(&mut self, sp: S, msg: &str) @@ -191,11 +197,23 @@ impl Diagnostic { message: &str, span: MultiSpan, render_span: Option) { + 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, + list: Vec) { let sub = SubDiagnostic { level: level, message: message.to_owned(), span: span, render_span: render_span, + list: list, }; self.children.push(sub); } diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 7dfea6b8951b0..24f1b86739da6 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -135,6 +135,7 @@ impl<'a> DiagnosticBuilder<'a> { forward!(pub fn warn(&mut self, msg: &str) -> &mut Self); forward!(pub fn span_warn>(&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) -> &mut Self); forward!(pub fn span_help>(&mut self, sp: S, msg: &str) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 808fe504b95cd..015997211bb3f 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -699,6 +699,7 @@ impl EmitterWriter { .to_string(), span: MultiSpan::new(), render_span: None, + list: vec![], }); } } @@ -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::(), + item) + }).collect::>() + .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), - _ => () + _ => (), } } } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 393d9341a0843..06d629c173256 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -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(); } @@ -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 { methods.iter() .take(5) .map(|method| self.format_method_suggestion(&*method)) .collect::>() - .join("\n - ") } - fn get_best_match(&self, methods: &[AssociatedItem]) -> String { + fn get_best_match(&self, methods: &[AssociatedItem]) -> Vec { 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 0b15c23909ca6..bb6f310fec813 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` = 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 e316466150703..ed1bcd318a4f6 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