Skip to content

Commit e57f061

Browse files
committed
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() ```
2 parents e4fee52 + 04e4a60 commit e57f061

File tree

4 files changed

+55
-18
lines changed

4 files changed

+55
-18
lines changed

src/librustc_errors/emitter.rs

+41-3
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,40 @@ impl EmitterWriter {
703703
}
704704
}
705705

706+
/// Add a left margin to every line but the first, given a padding length and the label being
707+
/// displayed.
708+
fn msg_with_padding(&self, msg: &str, padding: usize, label: &str) -> String {
709+
// The extra 5 ` ` is padding that's always needed to align to the `note: `:
710+
//
711+
// error: message
712+
// --> file.rs:13:20
713+
// |
714+
// 13 | <CODE>
715+
// | ^^^^
716+
// |
717+
// = note: multiline
718+
// message
719+
// ++^^^----xx
720+
// | | | |
721+
// | | | magic `2`
722+
// | | length of label
723+
// | magic `3`
724+
// `max_line_num_len`
725+
let padding = (0..padding + label.len() + 5)
726+
.map(|_| " ")
727+
.collect::<String>();
728+
729+
msg.split('\n').enumerate().fold("".to_owned(), |mut acc, x| {
730+
if x.0 != 0 {
731+
acc.push_str("\n");
732+
// Align every line with first one.
733+
acc.push_str(&padding);
734+
}
735+
acc.push_str(&x.1);
736+
acc
737+
})
738+
}
739+
706740
fn emit_message_default(&mut self,
707741
msp: &MultiSpan,
708742
msg: &str,
@@ -721,7 +755,9 @@ impl EmitterWriter {
721755
draw_note_separator(&mut buffer, 0, max_line_num_len + 1);
722756
buffer.append(0, &level.to_string(), Style::HeaderMsg);
723757
buffer.append(0, ": ", Style::NoStyle);
724-
buffer.append(0, msg, Style::NoStyle);
758+
759+
let message = self.msg_with_padding(msg, max_line_num_len, "note");
760+
buffer.append(0, &message, Style::NoStyle);
725761
} else {
726762
buffer.append(0, &level.to_string(), Style::Level(level.clone()));
727763
match code {
@@ -854,7 +890,9 @@ impl EmitterWriter {
854890

855891
buffer.append(0, &level.to_string(), Style::Level(level.clone()));
856892
buffer.append(0, ": ", Style::HeaderMsg);
857-
buffer.append(0, msg, Style::HeaderMsg);
893+
894+
let message = self.msg_with_padding(msg, max_line_num_len, "suggestion");
895+
buffer.append(0, &message, Style::HeaderMsg);
858896

859897
let lines = cm.span_to_lines(primary_span).unwrap();
860898

@@ -930,7 +968,7 @@ impl EmitterWriter {
930968
max_line_num_len,
931969
true) {
932970
Err(e) => panic!("failed to emit error: {}", e),
933-
_ => ()
971+
_ => (),
934972
}
935973
}
936974
}

src/librustc_typeck/check/demand.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
7171
let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
7272
if suggestions.len() > 0 {
7373
err.help(&format!("here are some functions which \
74-
might fulfill your needs:\n - {}",
75-
self.get_best_match(&suggestions)));
74+
might fulfill your needs:\n{}",
75+
self.get_best_match(&suggestions).join("\n")));
7676
};
7777
err.emit();
7878
}
7979
}
8080

8181
fn format_method_suggestion(&self, method: &AssociatedItem) -> String {
82-
format!(".{}({})",
82+
format!("- .{}({})",
8383
method.name,
8484
if self.has_no_input_arg(method) {
8585
""
@@ -88,15 +88,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
8888
})
8989
}
9090

91-
fn display_suggested_methods(&self, methods: &[AssociatedItem]) -> String {
91+
fn display_suggested_methods(&self, methods: &[AssociatedItem]) -> Vec<String> {
9292
methods.iter()
9393
.take(5)
9494
.map(|method| self.format_method_suggestion(&*method))
9595
.collect::<Vec<String>>()
96-
.join("\n - ")
9796
}
9897

99-
fn get_best_match(&self, methods: &[AssociatedItem]) -> String {
98+
fn get_best_match(&self, methods: &[AssociatedItem]) -> Vec<String> {
10099
let no_argument_methods: Vec<_> =
101100
methods.iter()
102101
.filter(|ref x| self.has_no_input_arg(&*x))

src/test/ui/resolve/token-error-correct-3.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ error[E0308]: mismatched types
3737
= note: expected type `()`
3838
= note: found type `std::result::Result<bool, std::io::Error>`
3939
= help: here are some functions which might fulfill your needs:
40-
- .unwrap()
41-
- .unwrap_err()
42-
- .unwrap_or_default()
40+
- .unwrap()
41+
- .unwrap_err()
42+
- .unwrap_or_default()
4343

4444
error: aborting due to previous error
4545

src/test/ui/span/coerce-suggestions.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ error[E0308]: mismatched types
77
= note: expected type `usize`
88
= note: found type `std::string::String`
99
= help: here are some functions which might fulfill your needs:
10-
- .capacity()
11-
- .len()
10+
- .capacity()
11+
- .len()
1212

1313
error[E0308]: mismatched types
1414
--> $DIR/coerce-suggestions.rs:23:19
@@ -19,10 +19,10 @@ error[E0308]: mismatched types
1919
= note: expected type `&str`
2020
= note: found type `std::string::String`
2121
= help: here are some functions which might fulfill your needs:
22-
- .as_str()
23-
- .trim()
24-
- .trim_left()
25-
- .trim_right()
22+
- .as_str()
23+
- .trim()
24+
- .trim_left()
25+
- .trim_right()
2626

2727
error[E0308]: mismatched types
2828
--> $DIR/coerce-suggestions.rs:30:10

0 commit comments

Comments
 (0)