1
Fork 0

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`
This commit is contained in:
bors 2022-02-25 00:46:04 +00:00
commit d4de1f230c
134 changed files with 1497 additions and 1143 deletions

View file

@ -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,

View file

@ -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

View file

@ -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(

View file

@ -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,

View file

@ -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>,
) {

View file

@ -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;

View file

@ -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();

View file

@ -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);
}
}

View file

@ -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,

View file

@ -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) => {

View file

@ -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)
}
}

View file

@ -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(

View file

@ -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)
}

View file

@ -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!(