Skip to content

Commit 5ccc698

Browse files
committed
Rollup merge of rust-lang#32756 - nikomatsakis:borrowck-snippet, r=nrc
Overhaul borrowck error messages and compiler error formatting generally This is a major overhaul of how the compiler reports errors. The primary goal is to be able to give many spans within the same overall context, such as this: ``` ./borrow-errors.rs:73:17: 73:20: error: cannot borrow `*vec` as immutable because previous closure requires unique access [E0501] 70 let append = |e| { ~~~ closure construction occurs here 71 vec.push(e) ~~~ previous borrow occurs due to use of `vec` in closure 72 }; 73 let data = &vec[3]; ~~~ borrow occurs here 74 } ~ borrow from closure ends here ``` However, in the process we made a number of other changes: - Removed the repetitive filenames from snippets and just give the line number. - Color the line numbers blue so they "fade away" - Remove the file name and line number from the error code suggestions since they don't seem to fit anymore. (This should probably happen in more places, like existing notes.) - Newlines in between errors to help group them better. This PR is not quite ready to land, but we thought it made sense to stop here and get some feedback from people at large. It'd be great if people can check out the branch and play with it. We'd be especially interested in hearing about cases that don't look good with the new formatting (I suspect they exist). Here is a checklist of some pending work items for this PR. Some of them may be best left for follow-up PRs: - [x] Accommodate multiple files in a `MultiSpan` (this should be easy) - In this case, we want to print filenames though. - [x] Remove duplicate E0500 code. - [x] Make the header message bold, rather than current hack that makes all errors/warnings bold - [x] Update warning text color (yellow is hard to read w/ a white background) Moved numerous follow-ups to: rust-lang#33240 Joint work with @jonathandturner. Fixes rust-lang#3533
2 parents d80497e + 9355a91 commit 5ccc698

File tree

169 files changed

+2956
-2201
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

169 files changed

+2956
-2201
lines changed

src/librustc/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1569,5 +1569,5 @@ register_diagnostics! {
15691569
E0490, // a value of type `..` is borrowed for too long
15701570
E0491, // in type `..`, reference has a longer lifetime than the data it...
15711571
E0495, // cannot infer an appropriate lifetime due to conflicting requirements
1572-
E0524, // expected a closure that implements `..` but this closure only implements `..`
1572+
E0525, // expected a closure that implements `..` but this closure only implements `..`
15731573
}

src/librustc/infer/error_reporting.rs

+26-31
Original file line numberDiff line numberDiff line change
@@ -249,12 +249,12 @@ pub trait ErrorReporting<'tcx> {
249249
terr: &TypeError<'tcx>)
250250
-> DiagnosticBuilder<'tcx>;
251251

252-
fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String>;
252+
fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<(String, String)>;
253253

254254
fn expected_found_str<T: fmt::Display + Resolvable<'tcx> + TypeFoldable<'tcx>>(
255255
&self,
256256
exp_found: &ty::error::ExpectedFound<T>)
257-
-> Option<String>;
257+
-> Option<(String, String)>;
258258

259259
fn report_concrete_failure(&self,
260260
origin: SubregionOrigin<'tcx>,
@@ -535,7 +535,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
535535
trace: TypeTrace<'tcx>,
536536
terr: &TypeError<'tcx>)
537537
-> DiagnosticBuilder<'tcx> {
538-
let expected_found_str = match self.values_str(&trace.values) {
538+
let (expected, found) = match self.values_str(&trace.values) {
539539
Some(v) => v,
540540
None => {
541541
return self.tcx.sess.diagnostic().struct_dummy(); /* derived error */
@@ -548,18 +548,17 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
548548
false
549549
};
550550

551-
let expected_found_str = if is_simple_error {
552-
expected_found_str
553-
} else {
554-
format!("{} ({})", expected_found_str, terr)
555-
};
556-
557551
let mut err = struct_span_err!(self.tcx.sess,
558552
trace.origin.span(),
559553
E0308,
560-
"{}: {}",
561-
trace.origin,
562-
expected_found_str);
554+
"{}",
555+
trace.origin);
556+
557+
if !is_simple_error {
558+
err = err.note_expected_found(&"type", &expected, &found);
559+
}
560+
561+
err = err.span_label(trace.origin.span(), &terr);
563562

564563
self.check_and_note_conflicting_crates(&mut err, terr, trace.origin.span());
565564

@@ -574,6 +573,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
574573
},
575574
_ => ()
576575
}
576+
577577
err
578578
}
579579

@@ -631,7 +631,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
631631

632632
/// Returns a string of the form "expected `{}`, found `{}`", or None if this is a derived
633633
/// error.
634-
fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String> {
634+
fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<(String, String)> {
635635
match *values {
636636
infer::Types(ref exp_found) => self.expected_found_str(exp_found),
637637
infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
@@ -642,7 +642,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
642642
fn expected_found_str<T: fmt::Display + Resolvable<'tcx> + TypeFoldable<'tcx>>(
643643
&self,
644644
exp_found: &ty::error::ExpectedFound<T>)
645-
-> Option<String>
645+
-> Option<(String, String)>
646646
{
647647
let expected = exp_found.expected.resolve(self);
648648
if expected.references_error() {
@@ -654,9 +654,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
654654
return None;
655655
}
656656

657-
Some(format!("expected `{}`, found `{}`",
658-
expected,
659-
found))
657+
Some((format!("{}", expected), format!("{}", found)))
660658
}
661659

662660
fn report_generic_bound_failure(&self,
@@ -684,10 +682,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
684682
E0309,
685683
"{} may not live long enough",
686684
labeled_user_string);
687-
err.fileline_help(origin.span(),
688-
&format!("consider adding an explicit lifetime bound `{}: {}`...",
689-
bound_kind,
690-
sub));
685+
err.help(&format!("consider adding an explicit lifetime bound `{}: {}`...",
686+
bound_kind,
687+
sub));
691688
err
692689
}
693690

@@ -698,10 +695,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
698695
E0310,
699696
"{} may not live long enough",
700697
labeled_user_string);
701-
err.fileline_help(origin.span(),
702-
&format!("consider adding an explicit lifetime \
703-
bound `{}: 'static`...",
704-
bound_kind));
698+
err.help(&format!("consider adding an explicit lifetime \
699+
bound `{}: 'static`...",
700+
bound_kind));
705701
err
706702
}
707703

@@ -712,9 +708,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
712708
E0311,
713709
"{} may not live long enough",
714710
labeled_user_string);
715-
err.fileline_help(origin.span(),
716-
&format!("consider adding an explicit lifetime bound for `{}`",
717-
bound_kind));
711+
err.help(&format!("consider adding an explicit lifetime bound for `{}`",
712+
bound_kind));
718713
self.tcx.note_and_explain_region(
719714
&mut err,
720715
&format!("{} must be valid for ", labeled_user_string),
@@ -1751,11 +1746,11 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
17511746
};
17521747

17531748
match self.values_str(&trace.values) {
1754-
Some(values_str) => {
1749+
Some((expected, found)) => {
17551750
err.span_note(
17561751
trace.origin.span(),
1757-
&format!("...so that {} ({})",
1758-
desc, values_str));
1752+
&format!("...so that {} (expected {}, found {})",
1753+
desc, expected, found));
17591754
}
17601755
None => {
17611756
// Really should avoid printing this error at

src/librustc/lint/context.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -456,17 +456,13 @@ pub fn raw_struct_lint<'a>(sess: &'a Session,
456456
it will become a hard error in a future release!");
457457
let citation = format!("for more information, see {}",
458458
future_incompatible.reference);
459-
if let Some(sp) = span {
460-
err.fileline_warn(sp, &explanation);
461-
err.fileline_note(sp, &citation);
462-
} else {
463-
err.warn(&explanation);
464-
err.note(&citation);
465-
}
459+
err.warn(&explanation);
460+
err.note(&citation);
466461
}
467462

468463
if let Some(span) = def {
469-
err.span_note(span, "lint level defined here");
464+
let explanation = "lint level defined here";
465+
err.span_note(span, &explanation);
470466
}
471467

472468
err
@@ -542,7 +538,7 @@ pub trait LintContext: Sized {
542538
let mut err = self.lookup(lint, Some(span), msg);
543539
if self.current_level(lint) != Level::Allow {
544540
if note_span == span {
545-
err.fileline_note(note_span, note);
541+
err.note(note);
546542
} else {
547543
err.span_note(note_span, note);
548544
}

src/librustc/session/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
567567
}
568568
config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
569569
};
570-
emitter.emit(None, msg, None, errors::Level::Fatal);
570+
emitter.emit(&MultiSpan::new(), msg, None, errors::Level::Fatal);
571571
panic!(errors::FatalError);
572572
}
573573

@@ -578,7 +578,7 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
578578
}
579579
config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
580580
};
581-
emitter.emit(None, msg, None, errors::Level::Warning);
581+
emitter.emit(&MultiSpan::new(), msg, None, errors::Level::Warning);
582582
}
583583

584584
// Err(0) means compilation was stopped, but no errors were found.

0 commit comments

Comments
 (0)