diff options
| author | bors <bors@rust-lang.org> | 2022-02-25 00:46:04 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-02-25 00:46:04 +0000 |
| commit | d4de1f230ca30b7ce08fbf453daebf8b2e7ffcc9 (patch) | |
| tree | 922a1d8bf2850b2f35dda5bc6cc14e9194c375c1 /compiler/rustc_borrowck/src | |
| parent | 4e82f35492ea5c78e19609bf4468f0a686d9a756 (diff) | |
| parent | b7e95dee65c35db8f8e07046d445b12d92cbae12 (diff) | |
| download | rust-d4de1f230ca30b7ce08fbf453daebf8b2e7ffcc9.tar.gz rust-d4de1f230ca30b7ce08fbf453daebf8b2e7ffcc9.zip | |
Auto merge of #93368 - eddyb:diagbld-guarantee, r=estebank
rustc_errors: let `DiagnosticBuilder::emit` return a "guarantee of emission".
That is, `DiagnosticBuilder` is now generic over the return type of `.emit()`, so we'll now have:
* `DiagnosticBuilder<ErrorReported>` for error (incl. fatal/bug) diagnostics
* can only be created via a `const L: Level`-generic constructor, that limits allowed variants via a `where` clause, so not even `rustc_errors` can accidentally bypass this limitation
* asserts `diagnostic.is_error()` on emission, just in case the construction restriction was bypassed (e.g. by replacing the whole `Diagnostic` inside `DiagnosticBuilder`)
* `.emit()` returns `ErrorReported`, as a "proof" token that `.emit()` was called
(though note that this isn't a real guarantee until after completing the work on
#69426)
* `DiagnosticBuilder<()>` for everything else (warnings, notes, etc.)
* can also be obtained from other `DiagnosticBuilder`s by calling `.forget_guarantee()`
This PR is a companion to other ongoing work, namely:
* #69426
and it's ongoing implementation:
#93222
the API changes in this PR are needed to get statically-checked "only errors produce `ErrorReported` from `.emit()`", but doesn't itself provide any really strong guarantees without those other `ErrorReported` changes
* #93244
would make the choices of API changes (esp. naming) in this PR fit better overall
In order to be able to let `.emit()` return anything trustable, several changes had to be made:
* `Diagnostic`'s `level` field is now private to `rustc_errors`, to disallow arbitrary "downgrade"s from "some kind of error" to "warning" (or anything else that doesn't cause compilation to fail)
* it's still possible to replace the whole `Diagnostic` inside the `DiagnosticBuilder`, sadly, that's harder to fix, but it's unlikely enough that we can paper over it with asserts on `.emit()`
* `.cancel()` now consumes `DiagnosticBuilder`, preventing `.emit()` calls on a cancelled diagnostic
* it's also now done internally, through `DiagnosticBuilder`-private state, instead of having a `Level::Cancelled` variant that can be read (or worse, written) by the user
* this removes a hazard of calling `.cancel()` on an error then continuing to attach details to it, and even expect to be able to `.emit()` it
* warnings were switched to *only* `can_emit_warnings` on emission (instead of pre-cancelling early)
* `struct_dummy` was removed (as it relied on a pre-`Cancelled` `Diagnostic`)
* since `.emit()` doesn't consume the `DiagnosticBuilder` <sub>(I tried and gave up, it's much more work than this PR)</sub>,
we have to make `.emit()` idempotent wrt the guarantees it returns
* thankfully, `err.emit(); err.emit();` can return `ErrorReported` both times, as the second `.emit()` call has no side-effects *only* because the first one did do the appropriate emission
* `&mut Diagnostic` is now used in a lot of function signatures, which used to take `&mut DiagnosticBuilder` (in the interest of not having to make those functions generic)
* the APIs were already mostly identical, allowing for low-effort porting to this new setup
* only some of the suggestion methods needed some rework, to have the extra `DiagnosticBuilder` functionality on the `Diagnostic` methods themselves (that change is also present in #93259)
* `.emit()`/`.cancel()` aren't available, but IMO calling them from an "error decorator/annotator" function isn't a good practice, and can lead to strange behavior (from the caller's perspective)
* `.downgrade_to_delayed_bug()` was added, letting you convert any `.is_error()` diagnostic into a `delay_span_bug` one (which works because in both cases the guarantees available are the same)
This PR should ideally be reviewed commit-by-commit, since there is a lot of fallout in each.
r? `@estebank` cc `@Manishearth` `@nikomatsakis` `@mark-i-m`
Diffstat (limited to 'compiler/rustc_borrowck/src')
14 files changed, 135 insertions, 109 deletions
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 7140cda8e4e..e2b6a48a9e8 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -1,9 +1,13 @@ -use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId}; +use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId, ErrorReported}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{MultiSpan, Span}; impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { - crate fn cannot_move_when_borrowed(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> { + crate fn cannot_move_when_borrowed( + &self, + span: Span, + desc: &str, + ) -> DiagnosticBuilder<'cx, ErrorReported> { struct_span_err!(self, span, E0505, "cannot move out of {} because it is borrowed", desc,) } @@ -13,7 +17,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { desc: &str, borrow_span: Span, borrow_desc: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let mut err = struct_span_err!( self, span, @@ -32,7 +36,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { span: Span, verb: &str, desc: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { struct_span_err!( self, span, @@ -51,7 +55,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { old_loan_span: Span, old_opt_via: &str, old_load_end_span: Option<Span>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) }; let mut err = struct_span_err!( @@ -99,7 +103,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { desc: &str, old_loan_span: Span, old_load_end_span: Option<Span>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let mut err = struct_span_err!( self, new_loan_span, @@ -132,7 +136,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { noun_old: &str, old_opt_via: &str, previous_end_span: Option<Span>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let mut err = struct_span_err!( self, new_loan_span, @@ -164,7 +168,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { old_opt_via: &str, previous_end_span: Option<Span>, second_borrow_desc: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let mut err = struct_span_err!( self, new_loan_span, @@ -200,7 +204,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { kind_old: &str, msg_old: &str, old_load_end_span: Option<Span>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) }; let mut err = struct_span_err!( @@ -243,7 +247,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { span: Span, borrow_span: Span, desc: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let mut err = struct_span_err!( self, span, @@ -262,12 +266,12 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { span: Span, desc: &str, is_arg: bool, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" }; struct_span_err!(self, span, E0384, "cannot assign {} {}", msg, desc) } - crate fn cannot_assign(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> { + crate fn cannot_assign(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx, ErrorReported> { struct_span_err!(self, span, E0594, "cannot assign to {}", desc) } @@ -275,7 +279,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, move_from_span: Span, move_from_desc: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc,) } @@ -287,7 +291,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { move_from_span: Span, ty: Ty<'_>, is_index: Option<bool>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let type_name = match (&ty.kind(), is_index) { (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array", (&ty::Slice(_), _) => "slice", @@ -309,7 +313,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, move_from_span: Span, container_ty: Ty<'_>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let mut err = struct_span_err!( self, move_from_span, @@ -327,7 +331,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { verb: &str, optional_adverb_for_moved: &str, moved_path: Option<String>, - ) -> DiagnosticBuilder<'tcx> { + ) -> DiagnosticBuilder<'tcx, ErrorReported> { let moved_path = moved_path.map(|mp| format!(": `{}`", mp)).unwrap_or_default(); struct_span_err!( @@ -346,7 +350,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { span: Span, path: &str, reason: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{}", path, reason,) } @@ -357,7 +361,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { immutable_place: &str, immutable_section: &str, action: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let mut err = struct_span_err!( self, mutate_span, @@ -376,7 +380,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, span: Span, yield_span: Span, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let mut err = struct_span_err!( self, span, @@ -387,7 +391,10 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { err } - crate fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> DiagnosticBuilder<'cx> { + crate fn cannot_borrow_across_destructor( + &self, + borrow_span: Span, + ) -> DiagnosticBuilder<'cx, ErrorReported> { struct_span_err!( self, borrow_span, @@ -400,7 +407,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, span: Span, path: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { struct_span_err!(self, span, E0597, "{} does not live long enough", path,) } @@ -410,7 +417,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { return_kind: &str, reference_desc: &str, path_desc: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let mut err = struct_span_err!( self, span, @@ -435,7 +442,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { closure_kind: &str, borrowed_path: &str, capture_span: Span, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let mut err = struct_span_err!( self, closure_span, @@ -454,11 +461,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { crate fn thread_local_value_does_not_live_long_enough( &self, span: Span, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { struct_span_err!(self, span, E0712, "thread-local variable borrowed past end of function",) } - crate fn temporary_value_borrowed_for_too_long(&self, span: Span) -> DiagnosticBuilder<'cx> { + crate fn temporary_value_borrowed_for_too_long( + &self, + span: Span, + ) -> DiagnosticBuilder<'cx, ErrorReported> { struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",) } @@ -467,7 +477,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { sp: S, msg: &str, code: DiagnosticId, - ) -> DiagnosticBuilder<'tcx> { + ) -> DiagnosticBuilder<'tcx, ErrorReported> { self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code) } } @@ -476,7 +486,7 @@ crate fn borrowed_data_escapes_closure<'tcx>( tcx: TyCtxt<'tcx>, escape_span: Span, escapes_from: &str, -) -> DiagnosticBuilder<'tcx> { +) -> DiagnosticBuilder<'tcx, ErrorReported> { struct_span_err!( tcx.sess, escape_span, diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 2a906e41b8c..3ef002bf740 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::DiagnosticBuilder; +use rustc_errors::{DiagnosticBuilder, ErrorReported}; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError; use rustc_infer::infer::region_constraints::Constraint; @@ -120,7 +120,11 @@ impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::Custo trait TypeOpInfo<'tcx> { /// Returns an error to be reported if rerunning the type op fails to /// recover the error's cause. - fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx>; + fn fallback_error( + &self, + tcx: TyCtxt<'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx, ErrorReported>; fn base_universe(&self) -> ty::UniverseIndex; @@ -130,7 +134,7 @@ trait TypeOpInfo<'tcx> { cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, - ) -> Option<DiagnosticBuilder<'tcx>>; + ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>>; fn report_error( &self, @@ -188,7 +192,11 @@ struct PredicateQuery<'tcx> { } impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { - fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn fallback_error( + &self, + tcx: TyCtxt<'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx, ErrorReported> { let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error"); err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate)); err @@ -204,7 +212,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, - ) -> Option<DiagnosticBuilder<'tcx>> { + ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> { tcx.infer_ctxt().enter_with_canonical( cause.span, &self.canonical_query, @@ -231,7 +239,11 @@ impl<'tcx, T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T> where T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx, { - fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn fallback_error( + &self, + tcx: TyCtxt<'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx, ErrorReported> { let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error"); err.note(&format!("could not normalize `{}`", self.canonical_query.value.value.value)); err @@ -247,7 +259,7 @@ where cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, - ) -> Option<DiagnosticBuilder<'tcx>> { + ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> { tcx.infer_ctxt().enter_with_canonical( cause.span, &self.canonical_query, @@ -288,7 +300,11 @@ struct AscribeUserTypeQuery<'tcx> { } impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { - fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn fallback_error( + &self, + tcx: TyCtxt<'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx, ErrorReported> { // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests, // and is only the fallback when the nice error fails. Consider improving this some more. tcx.sess.struct_span_err(span, "higher-ranked lifetime error") @@ -304,7 +320,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, - ) -> Option<DiagnosticBuilder<'tcx>> { + ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> { tcx.infer_ctxt().enter_with_canonical( cause.span, &self.canonical_query, @@ -329,7 +345,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>( infcx: &InferCtxt<'_, 'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, -) -> Option<DiagnosticBuilder<'tcx>> { +) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> { let tcx = infcx.tcx; // We generally shouldn't have errors here because the query was diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index baa59efbf8d..cd1f73d5298 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1,7 +1,7 @@ use either::Either; use rustc_const_eval::util::{CallDesugaringKind, CallKind}; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{AsyncGeneratorKind, GeneratorKind}; @@ -507,7 +507,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location: Location, (place, _span): (Place<'tcx>, Span), borrow: &BorrowData<'tcx>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let borrow_spans = self.retrieve_borrow_spans(borrow); let borrow_span = borrow_spans.args_or_use(); @@ -554,7 +554,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (place, span): (Place<'tcx>, Span), gen_borrow_kind: BorrowKind, issued_borrow: &BorrowData<'tcx>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let issued_spans = self.retrieve_borrow_spans(issued_borrow); let issued_span = issued_spans.args_or_use(); @@ -782,7 +782,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { #[instrument(level = "debug", skip(self, err))] fn suggest_using_local_if_applicable( &self, - err: &mut DiagnosticBuilder<'_>, + err: &mut Diagnostic, location: Location, (place, span): (Place<'tcx>, Span), gen_borrow_kind: BorrowKind, @@ -855,7 +855,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn suggest_split_at_mut_if_applicable( &self, - err: &mut DiagnosticBuilder<'_>, + err: &mut Diagnostic, place: Place<'tcx>, borrowed_place: Place<'tcx>, ) { @@ -1120,7 +1120,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { drop_span: Span, borrow_spans: UseSpans<'tcx>, explanation: BorrowExplanation, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { debug!( "report_local_value_does_not_live_long_enough(\ {:?}, {:?}, {:?}, {:?}, {:?}\ @@ -1298,7 +1298,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, drop_span: Span, borrow_span: Span, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { debug!( "report_thread_local_value_does_not_live_long_enough(\ {:?}, {:?}\ @@ -1325,7 +1325,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_spans: UseSpans<'tcx>, proper_span: Span, explanation: BorrowExplanation, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { debug!( "report_temporary_value_does_not_live_long_enough(\ {:?}, {:?}, {:?}, {:?}\ @@ -1384,7 +1384,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return_span: Span, category: ConstraintCategory, opt_place_desc: Option<&String>, - ) -> Option<DiagnosticBuilder<'cx>> { + ) -> Option<DiagnosticBuilder<'cx, ErrorReported>> { let return_kind = match category { ConstraintCategory::Return(_) => "return", ConstraintCategory::Yield => "yield", @@ -1483,7 +1483,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { category: ConstraintCategory, constraint_span: Span, captured_var: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let tcx = self.infcx.tcx; let args_span = use_span.args_or_use(); @@ -1560,7 +1560,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { upvar_span: Span, upvar_name: &str, escape_span: Span, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'cx, ErrorReported> { let tcx = self.infcx.tcx; let (_, escapes_from) = tcx.article_and_description(self.mir_def_id().to_def_id()); @@ -1835,7 +1835,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.buffer_error(err); } - fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut DiagnosticBuilder<'_>) { + fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut Diagnostic) { let tcx = self.infcx.tcx; if let ( Some(Terminator { kind: TerminatorKind::Call { from_hir_call: false, .. }, .. }), @@ -2362,11 +2362,7 @@ enum AnnotatedBorrowFnSignature<'tcx> { impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { /// Annotate the provided diagnostic with information about borrow from the fn signature that /// helps explain. - pub(crate) fn emit( - &self, - cx: &mut MirBorrowckCtxt<'_, 'tcx>, - diag: &mut DiagnosticBuilder<'_>, - ) -> String { + pub(crate) fn emit(&self, cx: &mut MirBorrowckCtxt<'_, 'tcx>, diag: &mut Diagnostic) -> String { match self { &AnnotatedBorrowFnSignature::Closure { argument_ty, argument_span } => { diag.span_label( diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index b1e5a211cf1..da6610c002e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -3,7 +3,7 @@ use std::collections::VecDeque; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc_errors::{Applicability, Diagnostic}; use rustc_index::vec::IndexVec; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::{ @@ -60,7 +60,7 @@ impl BorrowExplanation { tcx: TyCtxt<'tcx>, body: &Body<'tcx>, local_names: &IndexVec<Local, Option<Symbol>>, - err: &mut DiagnosticBuilder<'_>, + err: &mut Diagnostic, borrow_desc: &str, borrow_span: Option<Span>, multiple_borrow_span: Option<(Span, Span)>, @@ -275,7 +275,7 @@ impl BorrowExplanation { } pub(crate) fn add_lifetime_bound_suggestion_to_diagnostic( &self, - err: &mut DiagnosticBuilder<'_>, + err: &mut Diagnostic, category: &ConstraintCategory, span: Span, region_name: &RegionName, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 7f94e357f37..754856043b3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1,7 +1,7 @@ //! Borrow checker diagnostics. use rustc_const_eval::util::call_kind; -use rustc_errors::DiagnosticBuilder; +use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def::Namespace; use rustc_hir::def_id::DefId; @@ -57,7 +57,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &self, location: Location, place: PlaceRef<'tcx>, - diag: &mut DiagnosticBuilder<'_>, + diag: &mut Diagnostic, ) { debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place); let mut target = place.local_or_deref_local(); @@ -409,7 +409,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Add a note that a type does not implement `Copy` pub(super) fn note_type_does_not_implement_copy( &self, - err: &mut DiagnosticBuilder<'_>, + err: &mut Diagnostic, place_desc: &str, ty: Ty<'tcx>, span: Option<Span>, @@ -609,11 +609,7 @@ impl UseSpans<'_> { } // Add a span label to the arguments of the closure, if it exists. - pub(super) fn args_span_label( - self, - err: &mut DiagnosticBuilder<'_>, - message: impl Into<String>, - ) { + pub(super) fn args_span_label(self, err: &mut Diagnostic, message: impl Into<String>) { if let UseSpans::ClosureUse { args_span, .. } = self { err.span_label(args_span, message); } @@ -621,11 +617,7 @@ impl UseSpans<'_> { // Add a span label to the use of the captured variable, if it exists. // only adds label to the `path_span` - pub(super) fn var_span_label_path_only( - self, - err: &mut DiagnosticBuilder<'_>, - message: impl Into<String>, - ) { + pub(super) fn var_span_label_path_only(self, err: &mut Diagnostic, message: impl Into<String>) { if let UseSpans::ClosureUse { path_span, .. } = self { err.span_label(path_span, message); } @@ -634,7 +626,7 @@ impl UseSpans<'_> { // Add a span label to the use of the captured variable, if it exists. pub(super) fn var_span_label( self, - err: &mut DiagnosticBuilder<'_>, + err: &mut Diagnostic, message: impl Into<String>, kind_desc: impl Into<String>, ) { diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index d4f238ff71f..66f4c28a36d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -1,5 +1,5 @@ use rustc_const_eval::util::CallDesugaringKind; -use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::*; use rustc_middle::ty; @@ -271,7 +271,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { &mut self, place: Place<'tcx>, span: Span, - ) -> DiagnosticBuilder<'a> { + ) -> DiagnosticBuilder<'a, ErrorReported> { let description = if place.projection.len() == 1 { format!("static item {}", self.describe_any_place(place.as_ref())) } else { @@ -293,7 +293,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { deref_target_place: Place<'tcx>, span: Span, use_spans: Option<UseSpans<'tcx>>, - ) -> DiagnosticBuilder<'a> { + ) -> DiagnosticBuilder<'a, ErrorReported> { // Inspect the type of the content behind the // borrow to provide feedback about why this // was a move rather than a copy. @@ -441,12 +441,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err } - fn add_move_hints( - &self, - error: GroupedMoveError<'tcx>, - err: &mut DiagnosticBuilder<'a>, - span: Span, - ) { + fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diagnostic, span: Span) { match error { GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => { if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { @@ -505,7 +500,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } - fn add_move_error_suggestions(&self, err: &mut DiagnosticBuilder<'a>, binds_to: &[Local]) { + fn add_move_error_suggestions(&self, err: &mut Diagnostic, binds_to: &[Local]) { let mut suggestions: Vec<(Span, &str, String)> = Vec::new(); for local in binds_to { let bind_to = &self.body.local_decls[*local]; @@ -541,7 +536,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } - fn add_move_error_details(&self, err: &mut DiagnosticBuilder<'a>, binds_to: &[Local]) { + fn add_move_error_details(&self, err: &mut Diagnostic, binds_to: &[Local]) { for (j, local) in binds_to.iter().enumerate() { let bind_to = &self.body.local_decls[*local]; let binding_span = bind_to.source_info.span; diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 7d0dde53c2b..2c9bd8ea96e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -17,7 +17,7 @@ use rustc_span::{BytePos, Span}; use crate::diagnostics::BorrowedContentSource; use crate::MirBorrowckCtxt; use rustc_const_eval::util::collect_writes::FindAssignments; -use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc_errors::{Applicability, Diagnostic}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub(crate) enum AccessKind { @@ -689,7 +689,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { tcx: TyCtxt<'_>, id: &hir::def_id::DefId, the_place_err: PlaceRef<'tcx>, - err: &mut DiagnosticBuilder<'_>, + err: &mut Diagnostic, ) { let closure_local_def_id = id.expect_local(); let tables = tcx.typeck(closure_local_def_id); @@ -754,7 +754,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Attempt to search similar mutable associated items for suggestion. // In the future, attempt in all path but initially for RHS of for_loop - fn suggest_similar_mut_method_for_for_loop(&self, err: &mut DiagnosticBuilder<'_>) { + fn suggest_similar_mut_method_for_for_loop(&self, err: &mut Diagnostic) { use hir::{ BodyId, Expr, ExprKind::{Block, Call, DropTemps, Match, MethodCall}, @@ -843,7 +843,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } /// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected. - fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Span, act: &str) { + fn expected_fn_found_fn_mut_call(&self, err: &mut Diagnostic, sp: Span, act: &str) { err.span_label(sp, format!("cannot {}", act)); let hir = self.infcx.tcx.hir(); diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index 21f00af5c0c..de50f907eff 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -2,7 +2,7 @@ //! outlives constraints. use rustc_data_structures::fx::FxHashSet; -use rustc_errors::DiagnosticBuilder; +use rustc_errors::Diagnostic; use rustc_middle::ty::RegionVid; use smallvec::SmallVec; use std::collections::BTreeMap; @@ -162,7 +162,7 @@ impl OutlivesSuggestionBuilder { &mut self, mbcx: &MirBorrowckCtxt<'_, '_>, errci: &ErrorConstraintInfo, - diag: &mut DiagnosticBuilder<'_>, + diag: &mut Diagnostic, ) { // Emit an intermediate note. let fr_name = self.region_vid_to_name(mbcx, errci.fr); @@ -256,6 +256,6 @@ impl OutlivesSuggestionBuilder { diag.sort_span = mir_span.shrink_to_hi(); // Buffer the diagnostic - mbcx.buffer_error(diag); + mbcx.buffer_non_error_diag(diag); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index e6a323d676e..64f05f6004f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1,6 +1,6 @@ //! Error reporting machinery for lifetime errors. -use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported}; use rustc_infer::infer::{ error_reporting::nice_region_error::NiceRegionError, error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin, @@ -392,7 +392,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { &self, errci: &ErrorConstraintInfo, kind: ReturnConstraint, - ) -> DiagnosticBuilder<'tcx> { + ) -> DiagnosticBuilder<'tcx, ErrorReported> { let ErrorConstraintInfo { outlived_fr, span, .. } = errci; let mut diag = self @@ -469,7 +469,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// LL | ref_obj(x) /// | ^^^^^^^^^^ `x` escapes the function body here /// ``` - fn report_escaping_data_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> { + fn report_escaping_data_error( + &self, + errci: &ErrorConstraintInfo, + ) -> DiagnosticBuilder<'tcx, ErrorReported> { let ErrorConstraintInfo { span, category, .. } = errci; let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region( @@ -570,7 +573,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it /// | is returning data with lifetime `'b` /// ``` - fn report_general_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> { + fn report_general_error( + &self, + errci: &ErrorConstraintInfo, + ) -> DiagnosticBuilder<'tcx, ErrorReported> { let ErrorConstraintInfo { fr, fr_is_local, @@ -632,7 +638,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// ``` fn add_static_impl_trait_suggestion( &self, - diag: &mut DiagnosticBuilder<'tcx>, + diag: &mut Diagnostic, fr: RegionVid, // We need to pass `fr_name` - computing it again will label it twice. fr_name: RegionName, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 5d1d291d3b4..c9395492c9e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -1,7 +1,7 @@ use std::fmt::{self, Display}; use std::iter; -use rustc_errors::DiagnosticBuilder; +use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_middle::ty::print::RegionHighlightMode; @@ -98,7 +98,7 @@ impl RegionName { } } - crate fn highlight_region_name(&self, diag: &mut DiagnosticBuilder<'_>) { + crate fn highlight_region_name(&self, diag: &mut Diagnostic) { match &self.source { RegionNameSource::NamedFreeRegion(span) | RegionNameSource::NamedEarlyBoundRegion(span) => { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 753eed53068..590c5799ff6 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -379,7 +379,7 @@ fn do_mir_borrowck<'a, 'tcx>( // Convert any reservation warnings into lints. let reservation_warnings = mem::take(&mut mbcx.reservation_warnings); for (_, (place, span, location, bk, borrow)) in reservation_warnings { - let mut initial_diag = mbcx.report_conflicting_borrow(location, (place, span), bk, &borrow); + let initial_diag = mbcx.report_conflicting_borrow(location, (place, span), bk, &borrow); let scope = mbcx.body.source_info(location).scope; let lint_root = match &mbcx.body.source_scopes[scope].local_data { @@ -398,7 +398,7 @@ fn do_mir_borrowck<'a, 'tcx>( diag.message = initial_diag.styled_message().clone(); diag.span = initial_diag.span.clone(); - mbcx.buffer_error(diag); + mbcx.buffer_non_error_diag(diag); }, ); initial_diag.cancel(); @@ -2293,8 +2293,8 @@ mod error { /// when errors in the map are being re-added to the error buffer so that errors with the /// same primary span come out in a consistent order. buffered_move_errors: - BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>, - /// Errors to be reported buffer + BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorReported>)>, + /// Diagnostics to be reported buffer. buffered: Vec<Diagnostic>, /// Set to Some if we emit an error during borrowck tainted_by_errors: Option<ErrorReported>, @@ -2309,27 +2309,37 @@ mod error { } } - pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) { + // FIXME(eddyb) this is a suboptimal API because `tainted_by_errors` is + // set before any emission actually happens (weakening the guarantee). + pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorReported>) { self.tainted_by_errors = Some(ErrorReported {}); t.buffer(&mut self.buffered); } + pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) { + t.buffer(&mut self.buffered); + } + pub fn set_tainted_by_errors(&mut self) { self.tainted_by_errors = Some(ErrorReported {}); } } impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { - pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) { + pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorReported>) { self.errors.buffer_error(t); } + pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) { + self.errors.buffer_non_error_diag(t); + } + pub fn buffer_move_error( &mut self, move_out_indices: Vec<MoveOutIndex>, - place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>), + place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorReported>), ) -> bool { - if let Some((_, mut diag)) = + if let Some((_, diag)) = self.errors.buffered_move_errors.insert(move_out_indices, place_and_err) { // Cancel the old diagnostic so we don't ICE @@ -2365,7 +2375,7 @@ mod error { pub fn has_move_error( &self, move_out_indices: &[MoveOutIndex], - ) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx>)> { + ) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx, ErrorReported>)> { self.errors.buffered_move_errors.get(move_out_indices) } } diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index a16bdf28673..a2736fd1156 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -417,7 +417,7 @@ pub(super) fn dump_annotation<'a, 'tcx>( err.note(&format!("Inferred opaque type values:\n{:#?}", opaque_type_values)); } - errors.buffer_error(err); + errors.buffer_non_error_diag(err); } fn for_each_region_constraint( diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index b99fb00599e..3f0ce7dea00 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -5,6 +5,7 @@ use rustc_data_structures::binary_search_util; use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::scc::Sccs; +use rustc_errors::Diagnostic; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::CRATE_HIR_ID; use rustc_index::vec::IndexVec; @@ -510,7 +511,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } /// Adds annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`. - crate fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut rustc_errors::DiagnosticBuilder<'_>) { + crate fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diagnostic) { self.universal_regions.annotate(tcx, err) } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index d21a9d86e5b..478dbe31fba 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -14,7 +14,7 @@ use either::Either; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::DiagnosticBuilder; +use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; @@ -336,7 +336,7 @@ impl<'tcx> UniversalRegions<'tcx> { /// that this region imposes on others. The methods in this file /// handle the part about dumping the inference context internal /// state. - crate fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut DiagnosticBuilder<'_>) { + crate fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diagnostic) { match self.defining_ty { DefiningTy::Closure(def_id, substs) => { err.note(&format!( |
