rustc_errors: let DiagnosticBuilder::emit return a "guarantee of emission".

This commit is contained in:
Eduard-Mihai Burtescu 2022-01-27 09:44:25 +00:00
parent 0b9d70cf6d
commit b7e95dee65
83 changed files with 842 additions and 471 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_middle::ty::{self, Ty, TyCtxt};
use rustc_span::{MultiSpan, Span}; use rustc_span::{MultiSpan, Span};
impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { 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,) 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, desc: &str,
borrow_span: Span, borrow_span: Span,
borrow_desc: &str, borrow_desc: &str,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
span, span,
@ -32,7 +36,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
span: Span, span: Span,
verb: &str, verb: &str,
desc: &str, desc: &str,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
struct_span_err!( struct_span_err!(
self, self,
span, span,
@ -51,7 +55,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
old_loan_span: Span, old_loan_span: Span,
old_opt_via: &str, old_opt_via: &str,
old_load_end_span: Option<Span>, old_load_end_span: Option<Span>,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let via = let via =
|msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) }; |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) };
let mut err = struct_span_err!( let mut err = struct_span_err!(
@ -99,7 +103,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
desc: &str, desc: &str,
old_loan_span: Span, old_loan_span: Span,
old_load_end_span: Option<Span>, old_load_end_span: Option<Span>,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
new_loan_span, new_loan_span,
@ -132,7 +136,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
noun_old: &str, noun_old: &str,
old_opt_via: &str, old_opt_via: &str,
previous_end_span: Option<Span>, previous_end_span: Option<Span>,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
new_loan_span, new_loan_span,
@ -164,7 +168,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
old_opt_via: &str, old_opt_via: &str,
previous_end_span: Option<Span>, previous_end_span: Option<Span>,
second_borrow_desc: &str, second_borrow_desc: &str,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
new_loan_span, new_loan_span,
@ -200,7 +204,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
kind_old: &str, kind_old: &str,
msg_old: &str, msg_old: &str,
old_load_end_span: Option<Span>, old_load_end_span: Option<Span>,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let via = let via =
|msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) }; |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) };
let mut err = struct_span_err!( let mut err = struct_span_err!(
@ -243,7 +247,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
span: Span, span: Span,
borrow_span: Span, borrow_span: Span,
desc: &str, desc: &str,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
span, span,
@ -262,12 +266,12 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
span: Span, span: Span,
desc: &str, desc: &str,
is_arg: bool, is_arg: bool,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" }; let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" };
struct_span_err!(self, span, E0384, "cannot assign {} {}", msg, desc) 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) struct_span_err!(self, span, E0594, "cannot assign to {}", desc)
} }
@ -275,7 +279,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
&self, &self,
move_from_span: Span, move_from_span: Span,
move_from_desc: &str, move_from_desc: &str,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc,) 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, move_from_span: Span,
ty: Ty<'_>, ty: Ty<'_>,
is_index: Option<bool>, is_index: Option<bool>,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let type_name = match (&ty.kind(), is_index) { let type_name = match (&ty.kind(), is_index) {
(&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array", (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
(&ty::Slice(_), _) => "slice", (&ty::Slice(_), _) => "slice",
@ -309,7 +313,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
&self, &self,
move_from_span: Span, move_from_span: Span,
container_ty: Ty<'_>, container_ty: Ty<'_>,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
move_from_span, move_from_span,
@ -327,7 +331,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
verb: &str, verb: &str,
optional_adverb_for_moved: &str, optional_adverb_for_moved: &str,
moved_path: Option<String>, moved_path: Option<String>,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let moved_path = moved_path.map(|mp| format!(": `{}`", mp)).unwrap_or_default(); let moved_path = moved_path.map(|mp| format!(": `{}`", mp)).unwrap_or_default();
struct_span_err!( struct_span_err!(
@ -346,7 +350,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
span: Span, span: Span,
path: &str, path: &str,
reason: &str, reason: &str,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{}", path, reason,) 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_place: &str,
immutable_section: &str, immutable_section: &str,
action: &str, action: &str,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
mutate_span, mutate_span,
@ -376,7 +380,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
&self, &self,
span: Span, span: Span,
yield_span: Span, yield_span: Span,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
span, span,
@ -387,7 +391,10 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
err 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!( struct_span_err!(
self, self,
borrow_span, borrow_span,
@ -400,7 +407,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
&self, &self,
span: Span, span: Span,
path: &str, path: &str,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
struct_span_err!(self, span, E0597, "{} does not live long enough", path,) 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, return_kind: &str,
reference_desc: &str, reference_desc: &str,
path_desc: &str, path_desc: &str,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
span, span,
@ -435,7 +442,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
closure_kind: &str, closure_kind: &str,
borrowed_path: &str, borrowed_path: &str,
capture_span: Span, capture_span: Span,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
closure_span, closure_span,
@ -454,11 +461,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
crate fn thread_local_value_does_not_live_long_enough( crate fn thread_local_value_does_not_live_long_enough(
&self, &self,
span: Span, span: Span,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
struct_span_err!(self, span, E0712, "thread-local variable borrowed past end of function",) 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",) struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",)
} }
@ -467,7 +477,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
sp: S, sp: S,
msg: &str, msg: &str,
code: DiagnosticId, code: DiagnosticId,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code) 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>, tcx: TyCtxt<'tcx>,
escape_span: Span, escape_span: Span,
escapes_from: &str, escapes_from: &str,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
struct_span_err!( struct_span_err!(
tcx.sess, tcx.sess,
escape_span, 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::canonical::Canonical;
use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError; use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc_infer::infer::region_constraints::Constraint; 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> { trait TypeOpInfo<'tcx> {
/// Returns an error to be reported if rerunning the type op fails to /// Returns an error to be reported if rerunning the type op fails to
/// recover the error's cause. /// 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; fn base_universe(&self) -> ty::UniverseIndex;
@ -130,7 +134,7 @@ trait TypeOpInfo<'tcx> {
cause: ObligationCause<'tcx>, cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>, placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>, error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>>; ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>>;
fn report_error( fn report_error(
&self, &self,
@ -188,7 +192,11 @@ struct PredicateQuery<'tcx> {
} }
impl<'tcx> TypeOpInfo<'tcx> for 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"); 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.note(&format!("could not prove {}", self.canonical_query.value.value.predicate));
err err
@ -204,7 +212,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
cause: ObligationCause<'tcx>, cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>, placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>, error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
tcx.infer_ctxt().enter_with_canonical( tcx.infer_ctxt().enter_with_canonical(
cause.span, cause.span,
&self.canonical_query, &self.canonical_query,
@ -231,7 +239,11 @@ impl<'tcx, T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T>
where where
T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx, 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"); 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.note(&format!("could not normalize `{}`", self.canonical_query.value.value.value));
err err
@ -247,7 +259,7 @@ where
cause: ObligationCause<'tcx>, cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>, placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>, error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
tcx.infer_ctxt().enter_with_canonical( tcx.infer_ctxt().enter_with_canonical(
cause.span, cause.span,
&self.canonical_query, &self.canonical_query,
@ -288,7 +300,11 @@ struct AscribeUserTypeQuery<'tcx> {
} }
impl<'tcx> TypeOpInfo<'tcx> for 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, // 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. // 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") tcx.sess.struct_span_err(span, "higher-ranked lifetime error")
@ -304,7 +320,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
cause: ObligationCause<'tcx>, cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>, placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>, error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
tcx.infer_ctxt().enter_with_canonical( tcx.infer_ctxt().enter_with_canonical(
cause.span, cause.span,
&self.canonical_query, &self.canonical_query,
@ -329,7 +345,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'_, 'tcx>,
placeholder_region: ty::Region<'tcx>, placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>, error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
let tcx = infcx.tcx; let tcx = infcx.tcx;
// We generally shouldn't have errors here because the query was // We generally shouldn't have errors here because the query was

View File

@ -1,7 +1,7 @@
use either::Either; use either::Either;
use rustc_const_eval::util::{CallDesugaringKind, CallKind}; use rustc_const_eval::util::{CallDesugaringKind, CallKind};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{AsyncGeneratorKind, GeneratorKind}; use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
@ -507,7 +507,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
location: Location, location: Location,
(place, _span): (Place<'tcx>, Span), (place, _span): (Place<'tcx>, Span),
borrow: &BorrowData<'tcx>, borrow: &BorrowData<'tcx>,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let borrow_spans = self.retrieve_borrow_spans(borrow); let borrow_spans = self.retrieve_borrow_spans(borrow);
let borrow_span = borrow_spans.args_or_use(); let borrow_span = borrow_spans.args_or_use();
@ -554,7 +554,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(place, span): (Place<'tcx>, Span), (place, span): (Place<'tcx>, Span),
gen_borrow_kind: BorrowKind, gen_borrow_kind: BorrowKind,
issued_borrow: &BorrowData<'tcx>, issued_borrow: &BorrowData<'tcx>,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let issued_spans = self.retrieve_borrow_spans(issued_borrow); let issued_spans = self.retrieve_borrow_spans(issued_borrow);
let issued_span = issued_spans.args_or_use(); let issued_span = issued_spans.args_or_use();
@ -1120,7 +1120,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
drop_span: Span, drop_span: Span,
borrow_spans: UseSpans<'tcx>, borrow_spans: UseSpans<'tcx>,
explanation: BorrowExplanation, explanation: BorrowExplanation,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
debug!( debug!(
"report_local_value_does_not_live_long_enough(\ "report_local_value_does_not_live_long_enough(\
{:?}, {:?}, {:?}, {:?}, {:?}\ {:?}, {:?}, {:?}, {:?}, {:?}\
@ -1298,7 +1298,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&mut self, &mut self,
drop_span: Span, drop_span: Span,
borrow_span: Span, borrow_span: Span,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
debug!( debug!(
"report_thread_local_value_does_not_live_long_enough(\ "report_thread_local_value_does_not_live_long_enough(\
{:?}, {:?}\ {:?}, {:?}\
@ -1325,7 +1325,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
borrow_spans: UseSpans<'tcx>, borrow_spans: UseSpans<'tcx>,
proper_span: Span, proper_span: Span,
explanation: BorrowExplanation, explanation: BorrowExplanation,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
debug!( debug!(
"report_temporary_value_does_not_live_long_enough(\ "report_temporary_value_does_not_live_long_enough(\
{:?}, {:?}, {:?}, {:?}\ {:?}, {:?}, {:?}, {:?}\
@ -1384,7 +1384,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return_span: Span, return_span: Span,
category: ConstraintCategory, category: ConstraintCategory,
opt_place_desc: Option<&String>, opt_place_desc: Option<&String>,
) -> Option<DiagnosticBuilder<'cx>> { ) -> Option<DiagnosticBuilder<'cx, ErrorReported>> {
let return_kind = match category { let return_kind = match category {
ConstraintCategory::Return(_) => "return", ConstraintCategory::Return(_) => "return",
ConstraintCategory::Yield => "yield", ConstraintCategory::Yield => "yield",
@ -1483,7 +1483,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
category: ConstraintCategory, category: ConstraintCategory,
constraint_span: Span, constraint_span: Span,
captured_var: &str, captured_var: &str,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let tcx = self.infcx.tcx; let tcx = self.infcx.tcx;
let args_span = use_span.args_or_use(); let args_span = use_span.args_or_use();
@ -1560,7 +1560,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
upvar_span: Span, upvar_span: Span,
upvar_name: &str, upvar_name: &str,
escape_span: Span, escape_span: Span,
) -> DiagnosticBuilder<'cx> { ) -> DiagnosticBuilder<'cx, ErrorReported> {
let tcx = self.infcx.tcx; let tcx = self.infcx.tcx;
let (_, escapes_from) = tcx.article_and_description(self.mir_def_id().to_def_id()); let (_, escapes_from) = tcx.article_and_description(self.mir_def_id().to_def_id());

View File

@ -1,5 +1,5 @@
use rustc_const_eval::util::CallDesugaringKind; use rustc_const_eval::util::CallDesugaringKind;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty; use rustc_middle::ty;
@ -271,7 +271,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
&mut self, &mut self,
place: Place<'tcx>, place: Place<'tcx>,
span: Span, span: Span,
) -> DiagnosticBuilder<'a> { ) -> DiagnosticBuilder<'a, ErrorReported> {
let description = if place.projection.len() == 1 { let description = if place.projection.len() == 1 {
format!("static item {}", self.describe_any_place(place.as_ref())) format!("static item {}", self.describe_any_place(place.as_ref()))
} else { } else {
@ -293,7 +293,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
deref_target_place: Place<'tcx>, deref_target_place: Place<'tcx>,
span: Span, span: Span,
use_spans: Option<UseSpans<'tcx>>, use_spans: Option<UseSpans<'tcx>>,
) -> DiagnosticBuilder<'a> { ) -> DiagnosticBuilder<'a, ErrorReported> {
// Inspect the type of the content behind the // Inspect the type of the content behind the
// borrow to provide feedback about why this // borrow to provide feedback about why this
// was a move rather than a copy. // was a move rather than a copy.

View File

@ -256,6 +256,6 @@ impl OutlivesSuggestionBuilder {
diag.sort_span = mir_span.shrink_to_hi(); diag.sort_span = mir_span.shrink_to_hi();
// Buffer the diagnostic // 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. //! Error reporting machinery for lifetime errors.
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
use rustc_infer::infer::{ use rustc_infer::infer::{
error_reporting::nice_region_error::NiceRegionError, error_reporting::nice_region_error::NiceRegionError,
error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin, error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin,
@ -392,7 +392,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
&self, &self,
errci: &ErrorConstraintInfo, errci: &ErrorConstraintInfo,
kind: ReturnConstraint, kind: ReturnConstraint,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let ErrorConstraintInfo { outlived_fr, span, .. } = errci; let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
let mut diag = self let mut diag = self
@ -469,7 +469,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
/// LL | ref_obj(x) /// LL | ref_obj(x)
/// | ^^^^^^^^^^ `x` escapes the function body here /// | ^^^^^^^^^^ `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 ErrorConstraintInfo { span, category, .. } = errci;
let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region( 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 /// | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it
/// | is returning data with lifetime `'b` /// | 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 { let ErrorConstraintInfo {
fr, fr,
fr_is_local, fr_is_local,

View File

@ -398,7 +398,7 @@ fn do_mir_borrowck<'a, 'tcx>(
diag.message = initial_diag.styled_message().clone(); diag.message = initial_diag.styled_message().clone();
diag.span = initial_diag.span.clone(); diag.span = initial_diag.span.clone();
mbcx.buffer_error(diag); mbcx.buffer_non_error_diag(diag);
}, },
); );
initial_diag.cancel(); 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 /// 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. /// same primary span come out in a consistent order.
buffered_move_errors: buffered_move_errors:
BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>, BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorReported>)>,
/// Errors to be reported buffer /// Diagnostics to be reported buffer.
buffered: Vec<Diagnostic>, buffered: Vec<Diagnostic>,
/// Set to Some if we emit an error during borrowck /// Set to Some if we emit an error during borrowck
tainted_by_errors: Option<ErrorReported>, tainted_by_errors: Option<ErrorReported>,
@ -2309,25 +2309,35 @@ 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 {}); self.tainted_by_errors = Some(ErrorReported {});
t.buffer(&mut self.buffered); 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) { pub fn set_tainted_by_errors(&mut self) {
self.tainted_by_errors = Some(ErrorReported {}); self.tainted_by_errors = Some(ErrorReported {});
} }
} }
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { 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); 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( pub fn buffer_move_error(
&mut self, &mut self,
move_out_indices: Vec<MoveOutIndex>, move_out_indices: Vec<MoveOutIndex>,
place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>), place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorReported>),
) -> bool { ) -> bool {
if let Some((_, diag)) = if let Some((_, diag)) =
self.errors.buffered_move_errors.insert(move_out_indices, place_and_err) self.errors.buffered_move_errors.insert(move_out_indices, place_and_err)
@ -2365,7 +2375,7 @@ mod error {
pub fn has_move_error( pub fn has_move_error(
&self, &self,
move_out_indices: &[MoveOutIndex], move_out_indices: &[MoveOutIndex],
) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx>)> { ) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx, ErrorReported>)> {
self.errors.buffered_move_errors.get(move_out_indices) 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)); 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( fn for_each_region_constraint(

View File

@ -3,7 +3,7 @@ use rustc_ast::ptr::P;
use rustc_ast::token; use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream; use rustc_ast::tokenstream::TokenStream;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_errors::{Applicability, PResult};
use rustc_expand::base::{self, *}; use rustc_expand::base::{self, *};
use rustc_parse::parser::Parser; use rustc_parse::parser::Parser;
use rustc_parse_format as parse; use rustc_parse_format as parse;
@ -30,7 +30,7 @@ fn parse_args<'a>(
sp: Span, sp: Span,
tts: TokenStream, tts: TokenStream,
is_global_asm: bool, is_global_asm: bool,
) -> Result<AsmArgs, DiagnosticBuilder<'a>> { ) -> PResult<'a, AsmArgs> {
let mut p = ecx.new_parser_from_tts(tts); let mut p = ecx.new_parser_from_tts(tts);
let sess = &ecx.sess.parse_sess; let sess = &ecx.sess.parse_sess;
parse_asm_args(&mut p, sess, sp, is_global_asm) parse_asm_args(&mut p, sess, sp, is_global_asm)
@ -43,7 +43,7 @@ pub fn parse_asm_args<'a>(
sess: &'a ParseSess, sess: &'a ParseSess,
sp: Span, sp: Span,
is_global_asm: bool, is_global_asm: bool,
) -> Result<AsmArgs, DiagnosticBuilder<'a>> { ) -> PResult<'a, AsmArgs> {
let diag = &sess.span_diagnostic; let diag = &sess.span_diagnostic;
if p.token == token::Eof { if p.token == token::Eof {
@ -390,7 +390,7 @@ fn parse_options<'a>(
p: &mut Parser<'a>, p: &mut Parser<'a>,
args: &mut AsmArgs, args: &mut AsmArgs,
is_global_asm: bool, is_global_asm: bool,
) -> Result<(), DiagnosticBuilder<'a>> { ) -> PResult<'a, ()> {
let span_start = p.prev_token.span; let span_start = p.prev_token.span;
p.expect(&token::OpenDelim(token::DelimToken::Paren))?; p.expect(&token::OpenDelim(token::DelimToken::Paren))?;
@ -431,10 +431,7 @@ fn parse_options<'a>(
Ok(()) Ok(())
} }
fn parse_clobber_abi<'a>( fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a, ()> {
p: &mut Parser<'a>,
args: &mut AsmArgs,
) -> Result<(), DiagnosticBuilder<'a>> {
let span_start = p.prev_token.span; let span_start = p.prev_token.span;
p.expect(&token::OpenDelim(token::DelimToken::Paren))?; p.expect(&token::OpenDelim(token::DelimToken::Paren))?;
@ -501,7 +498,7 @@ fn parse_clobber_abi<'a>(
fn parse_reg<'a>( fn parse_reg<'a>(
p: &mut Parser<'a>, p: &mut Parser<'a>,
explicit_reg: &mut bool, explicit_reg: &mut bool,
) -> Result<ast::InlineAsmRegOrRegClass, DiagnosticBuilder<'a>> { ) -> PResult<'a, ast::InlineAsmRegOrRegClass> {
p.expect(&token::OpenDelim(token::DelimToken::Paren))?; p.expect(&token::OpenDelim(token::DelimToken::Paren))?;
let result = match p.token.uninterpolate().kind { let result = match p.token.uninterpolate().kind {
token::Ident(name, false) => ast::InlineAsmRegOrRegClass::RegClass(name), token::Ident(name, false) => ast::InlineAsmRegOrRegClass::RegClass(name),

View File

@ -4,7 +4,7 @@ use rustc_ast::token;
use rustc_ast::tokenstream::{DelimSpan, TokenStream}; use rustc_ast::tokenstream::{DelimSpan, TokenStream};
use rustc_ast::{self as ast, *}; use rustc_ast::{self as ast, *};
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_errors::{Applicability, PResult};
use rustc_expand::base::*; use rustc_expand::base::*;
use rustc_parse::parser::Parser; use rustc_parse::parser::Parser;
use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::symbol::{sym, Ident, Symbol};
@ -83,11 +83,7 @@ struct Assert {
custom_message: Option<TokenStream>, custom_message: Option<TokenStream>,
} }
fn parse_assert<'a>( fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult<'a, Assert> {
cx: &mut ExtCtxt<'a>,
sp: Span,
stream: TokenStream,
) -> Result<Assert, DiagnosticBuilder<'a>> {
let mut parser = cx.new_parser_from_tts(stream); let mut parser = cx.new_parser_from_tts(stream);
if parser.token == token::Eof { if parser.token == token::Eof {

View File

@ -6,7 +6,7 @@ use rustc_ast as ast;
use rustc_ast::token; use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream; use rustc_ast::tokenstream::TokenStream;
use rustc_attr as attr; use rustc_attr as attr;
use rustc_errors::DiagnosticBuilder; use rustc_errors::PResult;
use rustc_expand::base::{self, *}; use rustc_expand::base::{self, *};
use rustc_span::Span; use rustc_span::Span;
@ -29,11 +29,7 @@ pub fn expand_cfg(
} }
} }
fn parse_cfg<'a>( fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> {
cx: &mut ExtCtxt<'a>,
sp: Span,
tts: TokenStream,
) -> Result<ast::MetaItem, DiagnosticBuilder<'a>> {
let mut p = cx.new_parser_from_tts(tts); let mut p = cx.new_parser_from_tts(tts);
if p.token == token::Eof { if p.token == token::Eof {

View File

@ -7,7 +7,7 @@ use rustc_ast::tokenstream::TokenStream;
use rustc_ast::visit::{self, Visitor}; use rustc_ast::visit::{self, Visitor};
use rustc_ast::{token, BlockCheckMode, UnsafeSource}; use rustc_ast::{token, BlockCheckMode, UnsafeSource};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{pluralize, Applicability, DiagnosticBuilder}; use rustc_errors::{pluralize, Applicability, PResult};
use rustc_expand::base::{self, *}; use rustc_expand::base::{self, *};
use rustc_parse_format as parse; use rustc_parse_format as parse;
use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::symbol::{sym, Ident, Symbol};
@ -130,7 +130,7 @@ fn parse_args<'a>(
ecx: &mut ExtCtxt<'a>, ecx: &mut ExtCtxt<'a>,
sp: Span, sp: Span,
tts: TokenStream, tts: TokenStream,
) -> Result<(P<ast::Expr>, Vec<P<ast::Expr>>, FxHashMap<Symbol, usize>), DiagnosticBuilder<'a>> { ) -> PResult<'a, (P<ast::Expr>, Vec<P<ast::Expr>>, FxHashMap<Symbol, usize>)> {
let mut args = Vec::<P<ast::Expr>>::new(); let mut args = Vec::<P<ast::Expr>>::new();
let mut names = FxHashMap::<Symbol, usize>::default(); let mut names = FxHashMap::<Symbol, usize>::default();

View File

@ -376,9 +376,13 @@ fn get_test_runner(
match &*meta_list { match &*meta_list {
[single] => match single.meta_item() { [single] => match single.meta_item() {
Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()), Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()),
_ => sd.struct_span_err(span, "`test_runner` argument must be a path").emit(), _ => {
sd.struct_span_err(span, "`test_runner` argument must be a path").emit();
}
}, },
_ => sd.struct_span_err(span, "`#![test_runner(..)]` accepts exactly 1 argument").emit(), _ => {
sd.struct_span_err(span, "`#![test_runner(..)]` accepts exactly 1 argument").emit();
}
} }
None None
} }

View File

@ -1753,7 +1753,7 @@ impl SharedEmitterMain {
let msg = msg.strip_prefix("error: ").unwrap_or(&msg); let msg = msg.strip_prefix("error: ").unwrap_or(&msg);
let mut err = match level { let mut err = match level {
Level::Error { lint: false } => sess.struct_err(&msg), Level::Error { lint: false } => sess.struct_err(&msg).forget_guarantee(),
Level::Warning => sess.struct_warn(&msg), Level::Warning => sess.struct_warn(&msg),
Level::Note => sess.struct_note_without_error(&msg), Level::Note => sess.struct_note_without_error(&msg),
_ => bug!("Invalid inline asm diagnostic level"), _ => bug!("Invalid inline asm diagnostic level"),

View File

@ -1,7 +1,7 @@
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use rustc_errors::{DiagnosticBuilder, ErrorReported}; use rustc_errors::Diagnostic;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_middle::mir::AssertKind; use rustc_middle::mir::AssertKind;
use rustc_middle::ty::{layout::LayoutError, query::TyCtxtAt, ConstInt}; use rustc_middle::ty::{layout::LayoutError, query::TyCtxtAt, ConstInt};
@ -94,13 +94,13 @@ impl<'tcx> ConstEvalErr<'tcx> {
&self, &self,
tcx: TyCtxtAt<'tcx>, tcx: TyCtxtAt<'tcx>,
message: &str, message: &str,
emit: impl FnOnce(DiagnosticBuilder<'_>), decorate: impl FnOnce(&mut Diagnostic),
) -> ErrorHandled { ) -> ErrorHandled {
self.struct_generic(tcx, message, emit, None) self.struct_generic(tcx, message, decorate, None)
} }
pub fn report_as_error(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled { pub fn report_as_error(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled {
self.struct_error(tcx, message, |mut e| e.emit()) self.struct_error(tcx, message, |_| {})
} }
pub fn report_as_lint( pub fn report_as_lint(
@ -113,7 +113,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
self.struct_generic( self.struct_generic(
tcx, tcx,
message, message,
|mut lint: DiagnosticBuilder<'_>| { |lint: &mut Diagnostic| {
// Apply the span. // Apply the span.
if let Some(span) = span { if let Some(span) = span {
let primary_spans = lint.span.primary_spans().to_vec(); let primary_spans = lint.span.primary_spans().to_vec();
@ -127,7 +127,6 @@ impl<'tcx> ConstEvalErr<'tcx> {
} }
} }
} }
lint.emit();
}, },
Some(lint_root), Some(lint_root),
) )
@ -136,9 +135,8 @@ impl<'tcx> ConstEvalErr<'tcx> {
/// Create a diagnostic for this const eval error. /// Create a diagnostic for this const eval error.
/// ///
/// Sets the message passed in via `message` and adds span labels with detailed error /// Sets the message passed in via `message` and adds span labels with detailed error
/// information before handing control back to `emit` to do any final processing. /// information before handing control back to `decorate` to do any final annotations,
/// It's the caller's responsibility to call emit(), stash(), etc. within the `emit` /// after which the diagnostic is emitted.
/// function to dispose of the diagnostic properly.
/// ///
/// If `lint_root.is_some()` report it as a lint, else report it as a hard error. /// If `lint_root.is_some()` report it as a lint, else report it as a hard error.
/// (Except that for some errors, we ignore all that -- see `must_error` below.) /// (Except that for some errors, we ignore all that -- see `must_error` below.)
@ -146,10 +144,10 @@ impl<'tcx> ConstEvalErr<'tcx> {
&self, &self,
tcx: TyCtxtAt<'tcx>, tcx: TyCtxtAt<'tcx>,
message: &str, message: &str,
emit: impl FnOnce(DiagnosticBuilder<'_>), decorate: impl FnOnce(&mut Diagnostic),
lint_root: Option<hir::HirId>, lint_root: Option<hir::HirId>,
) -> ErrorHandled { ) -> ErrorHandled {
let finish = |mut err: DiagnosticBuilder<'_>, span_msg: Option<String>| { let finish = |err: &mut Diagnostic, span_msg: Option<String>| {
trace!("reporting const eval failure at {:?}", self.span); trace!("reporting const eval failure at {:?}", self.span);
if let Some(span_msg) = span_msg { if let Some(span_msg) = span_msg {
err.span_label(self.span, span_msg); err.span_label(self.span, span_msg);
@ -188,8 +186,8 @@ impl<'tcx> ConstEvalErr<'tcx> {
} }
flush_last_line(last_frame, times); flush_last_line(last_frame, times);
} }
// Let the caller finish the job. // Let the caller attach any additional information it wants.
emit(err) decorate(err);
}; };
// Special handling for certain errors // Special handling for certain errors
@ -206,8 +204,9 @@ impl<'tcx> ConstEvalErr<'tcx> {
// The `message` makes little sense here, this is a more serious error than the // The `message` makes little sense here, this is a more serious error than the
// caller thinks anyway. // caller thinks anyway.
// See <https://github.com/rust-lang/rust/pull/63152>. // See <https://github.com/rust-lang/rust/pull/63152>.
finish(struct_error(tcx, &self.error.to_string()), None); let mut err = struct_error(tcx, &self.error.to_string());
return ErrorHandled::Reported(ErrorReported); finish(&mut err, None);
return ErrorHandled::Reported(err.emit());
} }
_ => {} _ => {}
}; };
@ -223,13 +222,18 @@ impl<'tcx> ConstEvalErr<'tcx> {
rustc_session::lint::builtin::CONST_ERR, rustc_session::lint::builtin::CONST_ERR,
hir_id, hir_id,
tcx.span, tcx.span,
|lint| finish(lint.build(message), Some(err_msg)), |lint| {
let mut lint = lint.build(message);
finish(&mut lint, Some(err_msg));
lint.emit();
},
); );
ErrorHandled::Linted ErrorHandled::Linted
} else { } else {
// Report as hard error. // Report as hard error.
finish(struct_error(tcx, message), Some(err_msg)); let mut err = struct_error(tcx, message);
ErrorHandled::Reported(ErrorReported) finish(&mut err, Some(err_msg));
ErrorHandled::Reported(err.emit())
} }
} }
} }

View File

@ -361,7 +361,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
Err(err.struct_error( Err(err.struct_error(
ecx.tcx, ecx.tcx,
"it is undefined behavior to use this value", "it is undefined behavior to use this value",
|mut diag| { |diag| {
diag.note(note_on_undefined_behavior_error()); diag.note(note_on_undefined_behavior_error());
diag.note(&format!( diag.note(&format!(
"the raw bytes of the constant ({}", "the raw bytes of the constant ({}",
@ -370,7 +370,6 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
ecx.tcx.global_alloc(alloc_id).unwrap_memory() ecx.tcx.global_alloc(alloc_id).unwrap_memory()
) )
)); ));
diag.emit();
}, },
)) ))
} else { } else {

View File

@ -1,6 +1,6 @@
//! Concrete error types for all operations which may be invalid in a certain const context. //! Concrete error types for all operations which may be invalid in a certain const context.
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
@ -47,7 +47,11 @@ pub trait NonConstOp<'tcx>: std::fmt::Debug {
DiagnosticImportance::Primary DiagnosticImportance::Primary
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx>; fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported>;
} }
#[derive(Debug)] #[derive(Debug)]
@ -61,7 +65,11 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp {
} }
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
feature_err( feature_err(
&ccx.tcx.sess.parse_sess, &ccx.tcx.sess.parse_sess,
sym::const_fn_floating_point_arithmetic, sym::const_fn_floating_point_arithmetic,
@ -75,7 +83,11 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp {
#[derive(Debug)] #[derive(Debug)]
pub struct FnCallIndirect; pub struct FnCallIndirect;
impl<'tcx> NonConstOp<'tcx> for FnCallIndirect { impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
ccx.tcx.sess.struct_span_err(span, "function pointers are not allowed in const fn") ccx.tcx.sess.struct_span_err(span, "function pointers are not allowed in const fn")
} }
} }
@ -91,7 +103,11 @@ pub struct FnCallNonConst<'tcx> {
} }
impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
_: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
let FnCallNonConst { caller, callee, substs, span, from_hir_call } = *self; let FnCallNonConst { caller, callee, substs, span, from_hir_call } = *self;
let ConstCx { tcx, param_env, .. } = *ccx; let ConstCx { tcx, param_env, .. } = *ccx;
@ -312,7 +328,11 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
pub struct FnCallUnstable(pub DefId, pub Option<Symbol>); pub struct FnCallUnstable(pub DefId, pub Option<Symbol>);
impl<'tcx> NonConstOp<'tcx> for FnCallUnstable { impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
let FnCallUnstable(def_id, feature) = *self; let FnCallUnstable(def_id, feature) = *self;
let mut err = ccx.tcx.sess.struct_span_err( let mut err = ccx.tcx.sess.struct_span_err(
@ -346,7 +366,11 @@ impl<'tcx> NonConstOp<'tcx> for FnPtrCast {
} }
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
feature_err( feature_err(
&ccx.tcx.sess.parse_sess, &ccx.tcx.sess.parse_sess,
sym::const_fn_fn_ptr_basics, sym::const_fn_fn_ptr_basics,
@ -367,7 +391,11 @@ impl<'tcx> NonConstOp<'tcx> for Generator {
} }
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind()); let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind());
if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 { if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
feature_err(&ccx.tcx.sess.parse_sess, sym::const_async_blocks, span, &msg) feature_err(&ccx.tcx.sess.parse_sess, sym::const_async_blocks, span, &msg)
@ -380,7 +408,11 @@ impl<'tcx> NonConstOp<'tcx> for Generator {
#[derive(Debug)] #[derive(Debug)]
pub struct HeapAllocation; pub struct HeapAllocation;
impl<'tcx> NonConstOp<'tcx> for HeapAllocation { impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
ccx.tcx.sess, ccx.tcx.sess,
span, span,
@ -404,7 +436,11 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
#[derive(Debug)] #[derive(Debug)]
pub struct InlineAsm; pub struct InlineAsm;
impl<'tcx> NonConstOp<'tcx> for InlineAsm { impl<'tcx> NonConstOp<'tcx> for InlineAsm {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
struct_span_err!( struct_span_err!(
ccx.tcx.sess, ccx.tcx.sess,
span, span,
@ -420,7 +456,11 @@ pub struct LiveDrop {
pub dropped_at: Option<Span>, pub dropped_at: Option<Span>,
} }
impl<'tcx> NonConstOp<'tcx> for LiveDrop { impl<'tcx> NonConstOp<'tcx> for LiveDrop {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
ccx.tcx.sess, ccx.tcx.sess,
span, span,
@ -448,7 +488,11 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow {
// not additionally emit a feature gate error if activating the feature gate won't work. // not additionally emit a feature gate error if activating the feature gate won't work.
DiagnosticImportance::Secondary DiagnosticImportance::Secondary
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
feature_err( feature_err(
&ccx.tcx.sess.parse_sess, &ccx.tcx.sess.parse_sess,
sym::const_refs_to_cell, sym::const_refs_to_cell,
@ -464,7 +508,11 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow {
/// it in the future for static items. /// it in the future for static items.
pub struct CellBorrow; pub struct CellBorrow;
impl<'tcx> NonConstOp<'tcx> for CellBorrow { impl<'tcx> NonConstOp<'tcx> for CellBorrow {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
ccx.tcx.sess, ccx.tcx.sess,
span, span,
@ -511,7 +559,11 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow {
DiagnosticImportance::Secondary DiagnosticImportance::Secondary
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
let raw = match self.0 { let raw = match self.0 {
hir::BorrowKind::Raw => "raw ", hir::BorrowKind::Raw => "raw ",
hir::BorrowKind::Ref => "", hir::BorrowKind::Ref => "",
@ -550,7 +602,11 @@ impl<'tcx> NonConstOp<'tcx> for TransientMutBorrow {
Status::Unstable(sym::const_mut_refs) Status::Unstable(sym::const_mut_refs)
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
let raw = match self.0 { let raw = match self.0 {
hir::BorrowKind::Raw => "raw ", hir::BorrowKind::Raw => "raw ",
hir::BorrowKind::Ref => "", hir::BorrowKind::Ref => "",
@ -577,7 +633,11 @@ impl<'tcx> NonConstOp<'tcx> for MutDeref {
DiagnosticImportance::Secondary DiagnosticImportance::Secondary
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
feature_err( feature_err(
&ccx.tcx.sess.parse_sess, &ccx.tcx.sess.parse_sess,
sym::const_mut_refs, sym::const_mut_refs,
@ -591,7 +651,11 @@ impl<'tcx> NonConstOp<'tcx> for MutDeref {
#[derive(Debug)] #[derive(Debug)]
pub struct PanicNonStr; pub struct PanicNonStr;
impl<'tcx> NonConstOp<'tcx> for PanicNonStr { impl<'tcx> NonConstOp<'tcx> for PanicNonStr {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
ccx.tcx.sess.struct_span_err( ccx.tcx.sess.struct_span_err(
span, span,
"argument to `panic!()` in a const context must have type `&str`", "argument to `panic!()` in a const context must have type `&str`",
@ -605,7 +669,11 @@ impl<'tcx> NonConstOp<'tcx> for PanicNonStr {
#[derive(Debug)] #[derive(Debug)]
pub struct RawPtrComparison; pub struct RawPtrComparison;
impl<'tcx> NonConstOp<'tcx> for RawPtrComparison { impl<'tcx> NonConstOp<'tcx> for RawPtrComparison {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
let mut err = ccx let mut err = ccx
.tcx .tcx
.sess .sess
@ -625,7 +693,11 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref {
Status::Unstable(sym::const_mut_refs) Status::Unstable(sym::const_mut_refs)
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
feature_err( feature_err(
&ccx.tcx.sess.parse_sess, &ccx.tcx.sess.parse_sess,
sym::const_mut_refs, sym::const_mut_refs,
@ -641,7 +713,11 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref {
#[derive(Debug)] #[derive(Debug)]
pub struct RawPtrToIntCast; pub struct RawPtrToIntCast;
impl<'tcx> NonConstOp<'tcx> for RawPtrToIntCast { impl<'tcx> NonConstOp<'tcx> for RawPtrToIntCast {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
let mut err = ccx let mut err = ccx
.tcx .tcx
.sess .sess
@ -666,7 +742,11 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess {
} }
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
ccx.tcx.sess, ccx.tcx.sess,
span, span,
@ -692,7 +772,11 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess {
#[derive(Debug)] #[derive(Debug)]
pub struct ThreadLocalAccess; pub struct ThreadLocalAccess;
impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess { impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
struct_span_err!( struct_span_err!(
ccx.tcx.sess, ccx.tcx.sess,
span, span,
@ -723,7 +807,11 @@ pub mod ty {
} }
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
feature_err( feature_err(
&ccx.tcx.sess.parse_sess, &ccx.tcx.sess.parse_sess,
sym::const_mut_refs, sym::const_mut_refs,
@ -753,7 +841,11 @@ pub mod ty {
} }
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
feature_err( feature_err(
&ccx.tcx.sess.parse_sess, &ccx.tcx.sess.parse_sess,
sym::const_fn_fn_ptr_basics, sym::const_fn_fn_ptr_basics,
@ -770,7 +862,11 @@ pub mod ty {
Status::Unstable(sym::const_impl_trait) Status::Unstable(sym::const_impl_trait)
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
feature_err( feature_err(
&ccx.tcx.sess.parse_sess, &ccx.tcx.sess.parse_sess,
sym::const_impl_trait, sym::const_impl_trait,
@ -800,7 +896,11 @@ pub mod ty {
} }
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
let mut err = feature_err( let mut err = feature_err(
&ccx.tcx.sess.parse_sess, &ccx.tcx.sess.parse_sess,
sym::const_fn_trait_bound, sym::const_fn_trait_bound,
@ -839,7 +939,11 @@ pub mod ty {
} }
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
let mut err = feature_err( let mut err = feature_err(
&ccx.tcx.sess.parse_sess, &ccx.tcx.sess.parse_sess,
sym::const_fn_trait_bound, sym::const_fn_trait_bound,
@ -866,7 +970,11 @@ pub mod ty {
Status::Unstable(sym::const_trait_bound_opt_out) Status::Unstable(sym::const_trait_bound_opt_out)
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
feature_err( feature_err(
&ccx.tcx.sess.parse_sess, &ccx.tcx.sess.parse_sess,
sym::const_trait_bound_opt_out, sym::const_trait_bound_opt_out,

View File

@ -1,9 +1,10 @@
use crate::{Diagnostic, DiagnosticId, DiagnosticStyledString}; use crate::{Diagnostic, DiagnosticId, DiagnosticStyledString, ErrorReported};
use crate::{Handler, Level, StashKey}; use crate::{Handler, Level, StashKey};
use rustc_lint_defs::Applicability; use rustc_lint_defs::Applicability;
use rustc_span::{MultiSpan, Span}; use rustc_span::{MultiSpan, Span};
use std::fmt::{self, Debug}; use std::fmt::{self, Debug};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::thread::panicking; use std::thread::panicking;
use tracing::debug; use tracing::debug;
@ -15,7 +16,24 @@ use tracing::debug;
/// extending `HandlerFlags`, accessed via `self.handler.flags`. /// extending `HandlerFlags`, accessed via `self.handler.flags`.
#[must_use] #[must_use]
#[derive(Clone)] #[derive(Clone)]
pub struct DiagnosticBuilder<'a> { pub struct DiagnosticBuilder<'a, G: EmissionGuarantee> {
inner: DiagnosticBuilderInner<'a>,
_marker: PhantomData<G>,
}
/// This type exists only for `DiagnosticBuilder::forget_guarantee`, because it:
/// 1. lacks the `G` parameter and therefore `DiagnosticBuilder<G1>` can be
/// converted into `DiagnosticBuilder<G2>` while reusing the `inner` field
/// 2. can implement the `Drop` "bomb" instead of `DiagnosticBuilder`, as it
/// contains all of the data (`state` + `diagnostic`) of `DiagnosticBuilder`
///
/// The `diagnostic` field is not `Copy` and can't be moved out of whichever
/// type implements the `Drop` "bomb", but because of the above two facts, that
/// never needs to happen - instead, the whole `inner: DiagnosticBuilderInner`
/// can be moved out of a `DiagnosticBuilder` and into another.
#[must_use]
#[derive(Clone)]
struct DiagnosticBuilderInner<'a> {
state: DiagnosticBuilderState<'a>, state: DiagnosticBuilderState<'a>,
/// `Diagnostic` is a large type, and `DiagnosticBuilder` is often used as a /// `Diagnostic` is a large type, and `DiagnosticBuilder` is often used as a
@ -38,8 +56,8 @@ enum DiagnosticBuilderState<'a> {
/// assumed that `.emit()` was previously called, to end up in this state. /// assumed that `.emit()` was previously called, to end up in this state.
/// ///
/// While this is also used by `.cancel()`, this state is only observed by /// While this is also used by `.cancel()`, this state is only observed by
/// the `Drop` `impl` of `DiagnosticBuilder`, as `.cancel()` takes `self` /// the `Drop` `impl` of `DiagnosticBuilderInner`, as `.cancel()` takes
/// by-value specifically to prevent any attempts to `.emit()`. /// `self` by-value specifically to prevent any attempts to `.emit()`.
/// ///
// FIXME(eddyb) currently this doesn't prevent extending the `Diagnostic`, // FIXME(eddyb) currently this doesn't prevent extending the `Diagnostic`,
// despite that being potentially lossy, if important information is added // despite that being potentially lossy, if important information is added
@ -53,6 +71,133 @@ rustc_data_structures::static_assert_size!(
std::mem::size_of::<&Handler>() std::mem::size_of::<&Handler>()
); );
/// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee"
/// (or "proof") token that the emission happened.
pub trait EmissionGuarantee: Sized {
/// Implementation of `DiagnosticBuilder::emit`, fully controlled by each
/// `impl` of `EmissionGuarantee`, to make it impossible to create a value
/// of `Self` without actually performing the emission.
#[track_caller]
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self;
}
/// Private module for sealing the `IsError` helper trait.
mod sealed_level_is_error {
use crate::Level;
/// Sealed helper trait for statically checking that a `Level` is an error.
crate trait IsError<const L: Level> {}
impl IsError<{ Level::Bug }> for () {}
impl IsError<{ Level::DelayedBug }> for () {}
impl IsError<{ Level::Fatal }> for () {}
// NOTE(eddyb) `Level::Error { lint: true }` is also an error, but lints
// don't need error guarantees, as their levels are always dynamic.
impl IsError<{ Level::Error { lint: false } }> for () {}
}
impl<'a> DiagnosticBuilder<'a, ErrorReported> {
/// Convenience function for internal use, clients should use one of the
/// `struct_*` methods on [`Handler`].
crate fn new_guaranteeing_error<const L: Level>(handler: &'a Handler, message: &str) -> Self
where
(): sealed_level_is_error::IsError<L>,
{
Self {
inner: DiagnosticBuilderInner {
state: DiagnosticBuilderState::Emittable(handler),
diagnostic: Box::new(Diagnostic::new_with_code(L, None, message)),
},
_marker: PhantomData,
}
}
/// Discard the guarantee `.emit()` would return, in favor of having the
/// type `DiagnosticBuilder<'a, ()>`. This may be necessary whenever there
/// is a common codepath handling both errors and warnings.
pub fn forget_guarantee(self) -> DiagnosticBuilder<'a, ()> {
DiagnosticBuilder { inner: self.inner, _marker: PhantomData }
}
}
// FIXME(eddyb) make `ErrorReported` impossible to create outside `.emit()`.
impl EmissionGuarantee for ErrorReported {
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
match db.inner.state {
// First `.emit()` call, the `&Handler` is still available.
DiagnosticBuilderState::Emittable(handler) => {
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
handler.emit_diagnostic(&db.inner.diagnostic);
// Only allow a guarantee if the `level` wasn't switched to a
// non-error - the field isn't `pub`, but the whole `Diagnostic`
// can be overwritten with a new one, thanks to `DerefMut`.
assert!(
db.inner.diagnostic.is_error(),
"emitted non-error ({:?}) diagnostic \
from `DiagnosticBuilder<ErrorReported>`",
db.inner.diagnostic.level,
);
ErrorReported
}
// `.emit()` was previously called, disallowed from repeating it,
// but can take advantage of the previous `.emit()`'s guarantee
// still being applicable (i.e. as a form of idempotency).
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {
// Only allow a guarantee if the `level` wasn't switched to a
// non-error - the field isn't `pub`, but the whole `Diagnostic`
// can be overwritten with a new one, thanks to `DerefMut`.
assert!(
db.inner.diagnostic.is_error(),
"`DiagnosticBuilder<ErrorReported>`'s diagnostic \
became non-error ({:?}), after original `.emit()`",
db.inner.diagnostic.level,
);
ErrorReported
}
}
}
}
impl<'a> DiagnosticBuilder<'a, ()> {
/// Convenience function for internal use, clients should use one of the
/// `struct_*` methods on [`Handler`].
crate fn new(handler: &'a Handler, level: Level, message: &str) -> Self {
let diagnostic = Diagnostic::new_with_code(level, None, message);
Self::new_diagnostic(handler, diagnostic)
}
/// Creates a new `DiagnosticBuilder` with an already constructed
/// diagnostic.
crate fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
debug!("Created new diagnostic");
Self {
inner: DiagnosticBuilderInner {
state: DiagnosticBuilderState::Emittable(handler),
diagnostic: Box::new(diagnostic),
},
_marker: PhantomData,
}
}
}
// FIXME(eddyb) should there be a `Option<ErrorReported>` impl as well?
impl EmissionGuarantee for () {
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
match db.inner.state {
// First `.emit()` call, the `&Handler` is still available.
DiagnosticBuilderState::Emittable(handler) => {
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
handler.emit_diagnostic(&db.inner.diagnostic);
}
// `.emit()` was previously called, disallowed from repeating it.
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
}
}
}
/// In general, the `DiagnosticBuilder` uses deref to allow access to /// In general, the `DiagnosticBuilder` uses deref to allow access to
/// the fields and methods of the embedded `diagnostic` in a /// the fields and methods of the embedded `diagnostic` in a
/// transparent way. *However,* many of the methods are intended to /// transparent way. *However,* many of the methods are intended to
@ -83,52 +228,43 @@ macro_rules! forward {
$(#[$attrs])* $(#[$attrs])*
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")] #[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
pub fn $n(&mut self, $($name: $ty),*) -> &mut Self { pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
self.diagnostic.$n($($name),*); self.inner.diagnostic.$n($($name),*);
self self
} }
}; };
} }
impl<'a> Deref for DiagnosticBuilder<'a> { impl<G: EmissionGuarantee> Deref for DiagnosticBuilder<'_, G> {
type Target = Diagnostic; type Target = Diagnostic;
fn deref(&self) -> &Diagnostic { fn deref(&self) -> &Diagnostic {
&self.diagnostic &self.inner.diagnostic
} }
} }
impl<'a> DerefMut for DiagnosticBuilder<'a> { impl<G: EmissionGuarantee> DerefMut for DiagnosticBuilder<'_, G> {
fn deref_mut(&mut self) -> &mut Diagnostic { fn deref_mut(&mut self) -> &mut Diagnostic {
&mut self.diagnostic &mut self.inner.diagnostic
} }
} }
impl<'a> DiagnosticBuilder<'a> { impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
/// Emit the diagnostic. /// Emit the diagnostic.
pub fn emit(&mut self) { #[track_caller]
match self.state { pub fn emit(&mut self) -> G {
// First `.emit()` call, the `&Handler` is still available. G::diagnostic_builder_emit_producing_guarantee(self)
DiagnosticBuilderState::Emittable(handler) => {
handler.emit_diagnostic(&self);
self.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
}
// `.emit()` was previously called, disallowed from repeating it.
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {
// FIXME(eddyb) rely on this to return a "proof" that an error
// was/will be emitted, despite doing no emission *here and now*.
}
}
} }
/// Emit the diagnostic unless `delay` is true, /// Emit the diagnostic unless `delay` is true,
/// in which case the emission will be delayed as a bug. /// in which case the emission will be delayed as a bug.
/// ///
/// See `emit` and `delay_as_bug` for details. /// See `emit` and `delay_as_bug` for details.
pub fn emit_unless(&mut self, delay: bool) { #[track_caller]
pub fn emit_unless(&mut self, delay: bool) -> G {
if delay { if delay {
self.downgrade_to_delayed_bug(); self.downgrade_to_delayed_bug();
} }
self.emit(); self.emit()
} }
/// Cancel the diagnostic (a structured diagnostic must either be emitted or /// Cancel the diagnostic (a structured diagnostic must either be emitted or
@ -138,7 +274,7 @@ impl<'a> DiagnosticBuilder<'a> {
/// which may be expected to *guarantee* the emission of an error, either /// which may be expected to *guarantee* the emission of an error, either
/// at the time of the call, or through a prior `.emit()` call. /// at the time of the call, or through a prior `.emit()` call.
pub fn cancel(mut self) { pub fn cancel(mut self) {
self.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; self.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
drop(self); drop(self);
} }
@ -156,7 +292,7 @@ impl<'a> DiagnosticBuilder<'a> {
/// Converts the builder to a `Diagnostic` for later emission, /// Converts the builder to a `Diagnostic` for later emission,
/// unless handler has disabled such buffering, or `.emit()` was called. /// unless handler has disabled such buffering, or `.emit()` was called.
pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a Handler)> { pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a Handler)> {
let handler = match self.state { let handler = match self.inner.state {
// No `.emit()` calls, the `&Handler` is still available. // No `.emit()` calls, the `&Handler` is still available.
DiagnosticBuilderState::Emittable(handler) => handler, DiagnosticBuilderState::Emittable(handler) => handler,
// `.emit()` was previously called, nothing we can do. // `.emit()` was previously called, nothing we can do.
@ -172,7 +308,7 @@ impl<'a> DiagnosticBuilder<'a> {
// Take the `Diagnostic` by replacing it with a dummy. // Take the `Diagnostic` by replacing it with a dummy.
let dummy = Diagnostic::new(Level::Allow, ""); let dummy = Diagnostic::new(Level::Allow, "");
let diagnostic = std::mem::replace(&mut *self.diagnostic, dummy); let diagnostic = std::mem::replace(&mut *self.inner.diagnostic, dummy);
// Disable the ICE on `Drop`. // Disable the ICE on `Drop`.
self.cancel(); self.cancel();
@ -347,57 +483,27 @@ impl<'a> DiagnosticBuilder<'a> {
forward!(pub fn set_primary_message(&mut self, msg: impl Into<String>) -> &mut Self); forward!(pub fn set_primary_message(&mut self, msg: impl Into<String>) -> &mut Self);
forward!(pub fn set_span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self); forward!(pub fn set_span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self);
forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
/// Convenience function for internal use, clients should use one of the
/// `struct_*` methods on [`Handler`].
crate fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> {
DiagnosticBuilder::new_with_code(handler, level, None, message)
}
/// Convenience function for internal use, clients should use one of the
/// `struct_*` methods on [`Handler`].
crate fn new_with_code(
handler: &'a Handler,
level: Level,
code: Option<DiagnosticId>,
message: &str,
) -> DiagnosticBuilder<'a> {
let diagnostic = Diagnostic::new_with_code(level, code, message);
DiagnosticBuilder::new_diagnostic(handler, diagnostic)
}
/// Creates a new `DiagnosticBuilder` with an already constructed
/// diagnostic.
crate fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> {
debug!("Created new diagnostic");
DiagnosticBuilder {
state: DiagnosticBuilderState::Emittable(handler),
diagnostic: Box::new(diagnostic),
}
}
} }
impl<'a> Debug for DiagnosticBuilder<'a> { impl<G: EmissionGuarantee> Debug for DiagnosticBuilder<'_, G> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.diagnostic.fmt(f) self.inner.diagnostic.fmt(f)
} }
} }
/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or cancelled /// Destructor bomb - a `DiagnosticBuilder` must be either emitted or cancelled
/// or we emit a bug. /// or we emit a bug.
impl<'a> Drop for DiagnosticBuilder<'a> { impl Drop for DiagnosticBuilderInner<'_> {
fn drop(&mut self) { fn drop(&mut self) {
match self.state { match self.state {
// No `.emit()` or `.cancel()` calls. // No `.emit()` or `.cancel()` calls.
DiagnosticBuilderState::Emittable(handler) => { DiagnosticBuilderState::Emittable(handler) => {
if !panicking() { if !panicking() {
let mut db = DiagnosticBuilder::new( handler.emit_diagnostic(&Diagnostic::new(
handler,
Level::Bug, Level::Bug,
"the following error was constructed but not emitted", "the following error was constructed but not emitted",
); ));
db.emit(); handler.emit_diagnostic(&self.diagnostic);
handler.emit_diagnostic(&self);
panic!(); panic!();
} }
} }

View File

@ -9,6 +9,8 @@
#![feature(let_else)] #![feature(let_else)]
#![feature(nll)] #![feature(nll)]
#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))] #![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
#![feature(adt_const_params)]
#![allow(incomplete_features)]
#[macro_use] #[macro_use]
extern crate rustc_macros; extern crate rustc_macros;
@ -52,7 +54,7 @@ mod snippet;
mod styled_buffer; mod styled_buffer;
pub use snippet::Style; pub use snippet::Style;
pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>; pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a, ErrorReported>>;
// `PResult` is used a lot. Make sure it doesn't unintentionally get bigger. // `PResult` is used a lot. Make sure it doesn't unintentionally get bigger.
// (See also the comment on `DiagnosticBuilder`'s `diagnostic` field.) // (See also the comment on `DiagnosticBuilder`'s `diagnostic` field.)
@ -609,7 +611,7 @@ impl Handler {
} }
/// Steal a previously stashed diagnostic with the given `Span` and `StashKey` as the key. /// Steal a previously stashed diagnostic with the given `Span` and `StashKey` as the key.
pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option<DiagnosticBuilder<'_>> { pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option<DiagnosticBuilder<'_, ()>> {
self.inner self.inner
.borrow_mut() .borrow_mut()
.stashed_diagnostics .stashed_diagnostics
@ -627,7 +629,11 @@ impl Handler {
/// Attempting to `.emit()` the builder will only emit if either: /// Attempting to `.emit()` the builder will only emit if either:
/// * `can_emit_warnings` is `true` /// * `can_emit_warnings` is `true`
/// * `is_force_warn` was set in `DiagnosticId::Lint` /// * `is_force_warn` was set in `DiagnosticId::Lint`
pub fn struct_span_warn(&self, span: impl Into<MultiSpan>, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_span_warn(
&self,
span: impl Into<MultiSpan>,
msg: &str,
) -> DiagnosticBuilder<'_, ()> {
let mut result = self.struct_warn(msg); let mut result = self.struct_warn(msg);
result.set_span(span); result.set_span(span);
result result
@ -638,7 +644,7 @@ impl Handler {
&self, &self,
span: impl Into<MultiSpan>, span: impl Into<MultiSpan>,
msg: &str, msg: &str,
) -> DiagnosticBuilder<'_> { ) -> DiagnosticBuilder<'_, ()> {
let mut result = self.struct_allow(msg); let mut result = self.struct_allow(msg);
result.set_span(span); result.set_span(span);
result result
@ -651,7 +657,7 @@ impl Handler {
span: impl Into<MultiSpan>, span: impl Into<MultiSpan>,
msg: &str, msg: &str,
code: DiagnosticId, code: DiagnosticId,
) -> DiagnosticBuilder<'_> { ) -> DiagnosticBuilder<'_, ()> {
let mut result = self.struct_span_warn(span, msg); let mut result = self.struct_span_warn(span, msg);
result.code(code); result.code(code);
result result
@ -662,17 +668,21 @@ impl Handler {
/// Attempting to `.emit()` the builder will only emit if either: /// Attempting to `.emit()` the builder will only emit if either:
/// * `can_emit_warnings` is `true` /// * `can_emit_warnings` is `true`
/// * `is_force_warn` was set in `DiagnosticId::Lint` /// * `is_force_warn` was set in `DiagnosticId::Lint`
pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_, ()> {
DiagnosticBuilder::new(self, Level::Warning, msg) DiagnosticBuilder::new(self, Level::Warning, msg)
} }
/// Construct a builder at the `Allow` level with the `msg`. /// Construct a builder at the `Allow` level with the `msg`.
pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_, ()> {
DiagnosticBuilder::new(self, Level::Allow, msg) DiagnosticBuilder::new(self, Level::Allow, msg)
} }
/// Construct a builder at the `Error` level at the given `span` and with the `msg`. /// Construct a builder at the `Error` level at the given `span` and with the `msg`.
pub fn struct_span_err(&self, span: impl Into<MultiSpan>, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_span_err(
&self,
span: impl Into<MultiSpan>,
msg: &str,
) -> DiagnosticBuilder<'_, ErrorReported> {
let mut result = self.struct_err(msg); let mut result = self.struct_err(msg);
result.set_span(span); result.set_span(span);
result result
@ -684,7 +694,7 @@ impl Handler {
span: impl Into<MultiSpan>, span: impl Into<MultiSpan>,
msg: &str, msg: &str,
code: DiagnosticId, code: DiagnosticId,
) -> DiagnosticBuilder<'_> { ) -> DiagnosticBuilder<'_, ErrorReported> {
let mut result = self.struct_span_err(span, msg); let mut result = self.struct_span_err(span, msg);
result.code(code); result.code(code);
result result
@ -692,18 +702,22 @@ impl Handler {
/// Construct a builder at the `Error` level with the `msg`. /// Construct a builder at the `Error` level with the `msg`.
// FIXME: This method should be removed (every error should have an associated error code). // FIXME: This method should be removed (every error should have an associated error code).
pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorReported> {
DiagnosticBuilder::new(self, Level::Error { lint: false }, msg) DiagnosticBuilder::new_guaranteeing_error::<{ Level::Error { lint: false } }>(self, msg)
} }
/// This should only be used by `rustc_middle::lint::struct_lint_level`. Do not use it for hard errors. /// This should only be used by `rustc_middle::lint::struct_lint_level`. Do not use it for hard errors.
#[doc(hidden)] #[doc(hidden)]
pub fn struct_err_lint(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_err_lint(&self, msg: &str) -> DiagnosticBuilder<'_, ()> {
DiagnosticBuilder::new(self, Level::Error { lint: true }, msg) DiagnosticBuilder::new(self, Level::Error { lint: true }, msg)
} }
/// Construct a builder at the `Error` level with the `msg` and the `code`. /// Construct a builder at the `Error` level with the `msg` and the `code`.
pub fn struct_err_with_code(&self, msg: &str, code: DiagnosticId) -> DiagnosticBuilder<'_> { pub fn struct_err_with_code(
&self,
msg: &str,
code: DiagnosticId,
) -> DiagnosticBuilder<'_, ErrorReported> {
let mut result = self.struct_err(msg); let mut result = self.struct_err(msg);
result.code(code); result.code(code);
result result
@ -714,7 +728,7 @@ impl Handler {
&self, &self,
span: impl Into<MultiSpan>, span: impl Into<MultiSpan>,
msg: &str, msg: &str,
) -> DiagnosticBuilder<'_> { ) -> DiagnosticBuilder<'_, ErrorReported> {
let mut result = self.struct_fatal(msg); let mut result = self.struct_fatal(msg);
result.set_span(span); result.set_span(span);
result result
@ -726,24 +740,24 @@ impl Handler {
span: impl Into<MultiSpan>, span: impl Into<MultiSpan>,
msg: &str, msg: &str,
code: DiagnosticId, code: DiagnosticId,
) -> DiagnosticBuilder<'_> { ) -> DiagnosticBuilder<'_, ErrorReported> {
let mut result = self.struct_span_fatal(span, msg); let mut result = self.struct_span_fatal(span, msg);
result.code(code); result.code(code);
result result
} }
/// Construct a builder at the `Error` level with the `msg`. /// Construct a builder at the `Error` level with the `msg`.
pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorReported> {
DiagnosticBuilder::new(self, Level::Fatal, msg) DiagnosticBuilder::new_guaranteeing_error::<{ Level::Fatal }>(self, msg)
} }
/// Construct a builder at the `Help` level with the `msg`. /// Construct a builder at the `Help` level with the `msg`.
pub fn struct_help(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_help(&self, msg: &str) -> DiagnosticBuilder<'_, ()> {
DiagnosticBuilder::new(self, Level::Help, msg) DiagnosticBuilder::new(self, Level::Help, msg)
} }
/// Construct a builder at the `Note` level with the `msg`. /// Construct a builder at the `Note` level with the `msg`.
pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_, ()> {
DiagnosticBuilder::new(self, Level::Note, msg) DiagnosticBuilder::new(self, Level::Note, msg)
} }
@ -804,7 +818,7 @@ impl Handler {
self.emit_diag_at_span(Diagnostic::new(Note, msg), span); self.emit_diag_at_span(Diagnostic::new(Note, msg), span);
} }
pub fn span_note_diag(&self, span: Span, msg: &str) -> DiagnosticBuilder<'_> { pub fn span_note_diag(&self, span: Span, msg: &str) -> DiagnosticBuilder<'_, ()> {
let mut db = DiagnosticBuilder::new(self, Note, msg); let mut db = DiagnosticBuilder::new(self, Note, msg);
db.set_span(span); db.set_span(span);
db db
@ -1222,7 +1236,7 @@ impl DelayedDiagnostic {
} }
} }
#[derive(Copy, PartialEq, Clone, Hash, Debug, Encodable, Decodable)] #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)]
pub enum Level { pub enum Level {
Bug, Bug,
DelayedBug, DelayedBug,

View File

@ -10,7 +10,7 @@ use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind};
use rustc_attr::{self as attr, Deprecation, Stability}; use rustc_attr::{self as attr, Deprecation, Stability};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{self, Lrc}; use rustc_data_structures::sync::{self, Lrc};
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorReported}; use rustc_errors::{Applicability, DiagnosticBuilder, ErrorReported, PResult};
use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
use rustc_lint_defs::BuiltinLintDiagnostics; use rustc_lint_defs::BuiltinLintDiagnostics;
use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS}; use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
@ -1072,7 +1072,11 @@ impl<'a> ExtCtxt<'a> {
self.current_expansion.id.expansion_cause() self.current_expansion.id.expansion_cause()
} }
pub fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> { pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
msg: &str,
) -> DiagnosticBuilder<'a, ErrorReported> {
self.sess.parse_sess.span_diagnostic.struct_span_err(sp, msg) self.sess.parse_sess.span_diagnostic.struct_span_err(sp, msg)
} }
@ -1130,11 +1134,7 @@ impl<'a> ExtCtxt<'a> {
/// This unifies the logic used for resolving `include_X!`. /// This unifies the logic used for resolving `include_X!`.
/// ///
/// FIXME: move this to `rustc_builtin_macros` and make it private. /// FIXME: move this to `rustc_builtin_macros` and make it private.
pub fn resolve_path( pub fn resolve_path(&self, path: impl Into<PathBuf>, span: Span) -> PResult<'a, PathBuf> {
&self,
path: impl Into<PathBuf>,
span: Span,
) -> Result<PathBuf, DiagnosticBuilder<'a>> {
let path = path.into(); let path = path.into();
// Relative paths are resolved relative to the file in which they are found // Relative paths are resolved relative to the file in which they are found
@ -1174,7 +1174,7 @@ pub fn expr_to_spanned_string<'a>(
cx: &'a mut ExtCtxt<'_>, cx: &'a mut ExtCtxt<'_>,
expr: P<ast::Expr>, expr: P<ast::Expr>,
err_msg: &str, err_msg: &str,
) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a>, bool)>> { ) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a, ErrorReported>, bool)>> {
// Perform eager expansion on the expression. // Perform eager expansion on the expression.
// We want to be able to handle e.g., `concat!("foo", "bar")`. // We want to be able to handle e.g., `concat!("foo", "bar")`.
let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr();
@ -1233,7 +1233,9 @@ pub fn check_zero_tts(cx: &ExtCtxt<'_>, sp: Span, tts: TokenStream, name: &str)
pub fn parse_expr(p: &mut parser::Parser<'_>) -> Option<P<ast::Expr>> { pub fn parse_expr(p: &mut parser::Parser<'_>) -> Option<P<ast::Expr>> {
match p.parse_expr() { match p.parse_expr() {
Ok(e) => return Some(e), Ok(e) => return Some(e),
Err(mut err) => err.emit(), Err(mut err) => {
err.emit();
}
} }
while p.token != token::Eof { while p.token != token::Eof {
p.bump(); p.bump();

View File

@ -62,7 +62,7 @@ crate fn annotate_err_with_kind(err: &mut Diagnostic, kind: AstFragmentKind, spa
} }
fn emit_frag_parse_err( fn emit_frag_parse_err(
mut e: DiagnosticBuilder<'_>, mut e: DiagnosticBuilder<'_, rustc_errors::ErrorReported>,
parser: &Parser<'_>, parser: &Parser<'_>,
orig_parser: &mut Parser<'_>, orig_parser: &mut Parser<'_>,
site_span: Span, site_span: Span,

View File

@ -1,7 +1,7 @@
use crate::base::ModuleData; use crate::base::ModuleData;
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::{token, Attribute, Inline, Item}; use rustc_ast::{token, Attribute, Inline, Item};
use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorReported};
use rustc_parse::new_parser_from_file; use rustc_parse::new_parser_from_file;
use rustc_parse::validate_attr; use rustc_parse::validate_attr;
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
@ -39,7 +39,7 @@ pub enum ModError<'a> {
ModInBlock(Option<Ident>), ModInBlock(Option<Ident>),
FileNotFound(Ident, PathBuf, PathBuf), FileNotFound(Ident, PathBuf, PathBuf),
MultipleCandidates(Ident, PathBuf, PathBuf), MultipleCandidates(Ident, PathBuf, PathBuf),
ParserError(DiagnosticBuilder<'a>), ParserError(DiagnosticBuilder<'a, ErrorReported>),
} }
crate fn parse_external_mod( crate fn parse_external_mod(
@ -242,7 +242,7 @@ pub fn default_submod_path<'a>(
} }
impl ModError<'_> { impl ModError<'_> {
fn report(self, sess: &Session, span: Span) { fn report(self, sess: &Session, span: Span) -> ErrorReported {
let diag = &sess.parse_sess.span_diagnostic; let diag = &sess.parse_sess.span_diagnostic;
match self { match self {
ModError::CircularInclusion(file_paths) => { ModError::CircularInclusion(file_paths) => {

View File

@ -446,7 +446,9 @@ impl server::TokenStream for Rustc<'_, '_> {
} }
expr expr
}; };
let expr = expr.map_err(|mut err| err.emit())?; let expr = expr.map_err(|mut err| {
err.emit();
})?;
// Perform eager expansion on the expression. // Perform eager expansion on the expression.
let expr = self let expr = self

View File

@ -58,7 +58,7 @@ use crate::traits::{
}; };
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{pluralize, struct_span_err, Diagnostic}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorReported};
use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -230,7 +230,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
span: Span, span: Span,
hidden_ty: Ty<'tcx>, hidden_ty: Ty<'tcx>,
hidden_region: ty::Region<'tcx>, hidden_region: ty::Region<'tcx>,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
tcx.sess, tcx.sess,
span, span,
@ -2014,7 +2014,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
&self, &self,
trace: TypeTrace<'tcx>, trace: TypeTrace<'tcx>,
terr: &TypeError<'tcx>, terr: &TypeError<'tcx>,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
use crate::traits::ObligationCauseCode::MatchExpressionArm; use crate::traits::ObligationCauseCode::MatchExpressionArm;
debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr); debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
@ -2222,7 +2222,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
origin: Option<SubregionOrigin<'tcx>>, origin: Option<SubregionOrigin<'tcx>>,
bound_kind: GenericKind<'tcx>, bound_kind: GenericKind<'tcx>,
sub: Region<'tcx>, sub: Region<'tcx>,
) -> DiagnosticBuilder<'a> { ) -> DiagnosticBuilder<'a, ErrorReported> {
let hir = self.tcx.hir(); let hir = self.tcx.hir();
// Attempt to obtain the span of the parameter so we can // Attempt to obtain the span of the parameter so we can
// suggest adding an explicit lifetime bound to it. // suggest adding an explicit lifetime bound to it.
@ -2648,7 +2648,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
fn report_inference_failure( fn report_inference_failure(
&self, &self,
var_origin: RegionVariableOrigin, var_origin: RegionVariableOrigin,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let br_string = |br: ty::BoundRegionKind| { let br_string = |br: ty::BoundRegionKind| {
let mut s = match br { let mut s = match br {
ty::BrNamed(_, name) => name.to_string(), ty::BrNamed(_, name) => name.to_string(),

View File

@ -1,6 +1,8 @@
use crate::infer::type_variable::TypeVariableOriginKind; use crate::infer::type_variable::TypeVariableOriginKind;
use crate::infer::{InferCtxt, Symbol}; use crate::infer::{InferCtxt, Symbol};
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorReported,
};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::def::{DefKind, Namespace};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -491,7 +493,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
arg: GenericArg<'tcx>, arg: GenericArg<'tcx>,
impl_candidates: Vec<ty::TraitRef<'tcx>>, impl_candidates: Vec<ty::TraitRef<'tcx>>,
error_code: TypeAnnotationNeeded, error_code: TypeAnnotationNeeded,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let arg = self.resolve_vars_if_possible(arg); let arg = self.resolve_vars_if_possible(arg);
let arg_data = self.extract_inference_diagnostics_data(arg, None); let arg_data = self.extract_inference_diagnostics_data(arg, None);
@ -918,7 +920,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
kind: hir::GeneratorKind, kind: hir::GeneratorKind,
span: Span, span: Span,
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let ty = self.resolve_vars_if_possible(ty); let ty = self.resolve_vars_if_possible(ty);
let data = self.extract_inference_diagnostics_data(ty.into(), None); let data = self.extract_inference_diagnostics_data(ty.into(), None);

View File

@ -46,7 +46,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
self.infcx.tcx self.infcx.tcx
} }
pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'tcx>> { pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
// Due to the improved diagnostics returned by the MIR borrow checker, only a subset of // Due to the improved diagnostics returned by the MIR borrow checker, only a subset of
// the nice region errors are required when running under the MIR borrow checker. // the nice region errors are required when running under the MIR borrow checker.
self.try_report_named_anon_conflict().or_else(|| self.try_report_placeholder_conflict()) self.try_report_named_anon_conflict().or_else(|| self.try_report_placeholder_conflict())

View File

@ -2,13 +2,15 @@
//! where one region is named and the other is anonymous. //! where one region is named and the other is anonymous.
use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type; use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
use rustc_middle::ty; use rustc_middle::ty;
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// When given a `ConcreteFailure` for a function with parameters containing a named region and /// When given a `ConcreteFailure` for a function with parameters containing a named region and
/// an anonymous region, emit an descriptive diagnostic error. /// an anonymous region, emit an descriptive diagnostic error.
pub(super) fn try_report_named_anon_conflict(&self) -> Option<DiagnosticBuilder<'tcx>> { pub(super) fn try_report_named_anon_conflict(
&self,
) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
let (span, sub, sup) = self.regions()?; let (span, sub, sup) = self.regions()?;
debug!( debug!(

View File

@ -4,7 +4,7 @@ use crate::infer::ValuePairs;
use crate::infer::{SubregionOrigin, TypeTrace}; use crate::infer::{SubregionOrigin, TypeTrace};
use crate::traits::{ObligationCause, ObligationCauseCode}; use crate::traits::{ObligationCause, ObligationCauseCode};
use rustc_data_structures::intern::Interned; use rustc_data_structures::intern::Interned;
use rustc_errors::{Diagnostic, DiagnosticBuilder}; use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorReported};
use rustc_hir::def::Namespace; use rustc_hir::def::Namespace;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::error::ExpectedFound;
@ -17,7 +17,9 @@ use std::fmt::{self, Write};
impl<'tcx> NiceRegionError<'_, 'tcx> { impl<'tcx> NiceRegionError<'_, 'tcx> {
/// When given a `ConcreteFailure` for a function with arguments containing a named region and /// When given a `ConcreteFailure` for a function with arguments containing a named region and
/// an anonymous region, emit a descriptive diagnostic error. /// an anonymous region, emit a descriptive diagnostic error.
pub(super) fn try_report_placeholder_conflict(&self) -> Option<DiagnosticBuilder<'tcx>> { pub(super) fn try_report_placeholder_conflict(
&self,
) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
match &self.error { match &self.error {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// NB. The ordering of cases in this match is very // NB. The ordering of cases in this match is very
@ -153,7 +155,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
sub_placeholder: Option<Region<'tcx>>, sub_placeholder: Option<Region<'tcx>>,
sup_placeholder: Option<Region<'tcx>>, sup_placeholder: Option<Region<'tcx>>,
value_pairs: &ValuePairs<'tcx>, value_pairs: &ValuePairs<'tcx>,
) -> Option<DiagnosticBuilder<'tcx>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
let (expected_substs, found_substs, trait_def_id) = match value_pairs { let (expected_substs, found_substs, trait_def_id) = match value_pairs {
ValuePairs::TraitRefs(ExpectedFound { expected, found }) ValuePairs::TraitRefs(ExpectedFound { expected, found })
if expected.def_id == found.def_id => if expected.def_id == found.def_id =>
@ -201,7 +203,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
trait_def_id: DefId, trait_def_id: DefId,
expected_substs: SubstsRef<'tcx>, expected_substs: SubstsRef<'tcx>,
actual_substs: SubstsRef<'tcx>, actual_substs: SubstsRef<'tcx>,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let span = cause.span(self.tcx()); let span = cause.span(self.tcx());
let msg = format!( let msg = format!(
"implementation of `{}` is not general enough", "implementation of `{}` is not general enough",

View File

@ -1,6 +1,6 @@
use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt}; use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt};
use crate::infer::{self, InferCtxt, SubregionOrigin}; use crate::infer::{self, InferCtxt, SubregionOrigin};
use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder}; use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, ErrorReported};
use rustc_middle::traits::ObligationCauseCode; use rustc_middle::traits::ObligationCauseCode;
use rustc_middle::ty::error::TypeError; use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{self, Region}; use rustc_middle::ty::{self, Region};
@ -109,7 +109,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
origin: SubregionOrigin<'tcx>, origin: SubregionOrigin<'tcx>,
sub: Region<'tcx>, sub: Region<'tcx>,
sup: Region<'tcx>, sup: Region<'tcx>,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
match origin { match origin {
infer::Subtype(box trace) => { infer::Subtype(box trace) => {
let terr = TypeError::RegionsDoesNotOutlive(sup, sub); let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
@ -401,7 +401,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
placeholder_origin: SubregionOrigin<'tcx>, placeholder_origin: SubregionOrigin<'tcx>,
sub: Region<'tcx>, sub: Region<'tcx>,
sup: Region<'tcx>, sup: Region<'tcx>,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
// I can't think how to do better than this right now. -nikomatsakis // I can't think how to do better than this right now. -nikomatsakis
debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure"); debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
match placeholder_origin { match placeholder_origin {

View File

@ -14,7 +14,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_data_structures::undo_log::Rollback; use rustc_data_structures::undo_log::Rollback;
use rustc_data_structures::unify as ut; use rustc_data_structures::unify as ut;
use rustc_errors::DiagnosticBuilder; use rustc_errors::{DiagnosticBuilder, ErrorReported};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
@ -1475,9 +1475,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
sp: Span, sp: Span,
mk_diag: M, mk_diag: M,
actual_ty: Ty<'tcx>, actual_ty: Ty<'tcx>,
) -> DiagnosticBuilder<'tcx> ) -> DiagnosticBuilder<'tcx, ErrorReported>
where where
M: FnOnce(String) -> DiagnosticBuilder<'tcx>, M: FnOnce(String) -> DiagnosticBuilder<'tcx, ErrorReported>,
{ {
let actual_ty = self.resolve_vars_if_possible(actual_ty); let actual_ty = self.resolve_vars_if_possible(actual_ty);
debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty); debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
@ -1498,7 +1498,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
expected: Ty<'tcx>, expected: Ty<'tcx>,
actual: Ty<'tcx>, actual: Ty<'tcx>,
err: TypeError<'tcx>, err: TypeError<'tcx>,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let trace = TypeTrace::types(cause, true, expected, actual); let trace = TypeTrace::types(cause, true, expected, actual);
self.report_and_explain_type_error(trace, &err) self.report_and_explain_type_error(trace, &err)
} }
@ -1509,7 +1509,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
expected: ty::Const<'tcx>, expected: ty::Const<'tcx>,
actual: ty::Const<'tcx>, actual: ty::Const<'tcx>,
err: TypeError<'tcx>, err: TypeError<'tcx>,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let trace = TypeTrace::consts(cause, true, expected, actual); let trace = TypeTrace::consts(cause, true, expected, actual);
self.report_and_explain_type_error(trace, &err) self.report_and_explain_type_error(trace, &err)
} }

View File

@ -2,7 +2,7 @@ use super::ObjectSafetyViolation;
use crate::infer::InferCtxt; use crate::infer::InferCtxt;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorReported};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
@ -17,7 +17,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
impl_item_def_id: DefId, impl_item_def_id: DefId,
trait_item_def_id: DefId, trait_item_def_id: DefId,
requirement: &dyn fmt::Display, requirement: &dyn fmt::Display,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let msg = "impl has stricter requirements than trait"; let msg = "impl has stricter requirements than trait";
let sp = self.tcx.sess.source_map().guess_head_span(error_span); let sp = self.tcx.sess.source_map().guess_head_span(error_span);
@ -40,7 +40,7 @@ pub fn report_object_safety_error<'tcx>(
span: Span, span: Span,
trait_def_id: DefId, trait_def_id: DefId,
violations: &[ObjectSafetyViolation], violations: &[ObjectSafetyViolation],
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let trait_str = tcx.def_path_str(trait_def_id); let trait_str = tcx.def_path_str(trait_def_id);
let trait_span = tcx.hir().get_if_local(trait_def_id).and_then(|node| match node { let trait_span = tcx.hir().get_if_local(trait_def_id).and_then(|node| match node {
hir::Node::Item(item) => Some(item.ident.span), hir::Node::Item(item) => Some(item.ident.span),

View File

@ -319,7 +319,7 @@ impl LintStore {
) { ) {
let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name); let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name);
if lint_name_only == crate::WARNINGS.name_lower() && level == Level::ForceWarn { if lint_name_only == crate::WARNINGS.name_lower() && level == Level::ForceWarn {
return struct_span_err!( struct_span_err!(
sess, sess,
DUMMY_SP, DUMMY_SP,
E0602, E0602,
@ -327,6 +327,7 @@ impl LintStore {
crate::WARNINGS.name_lower() crate::WARNINGS.name_lower()
) )
.emit(); .emit();
return;
} }
let db = match self.check_lint_name(lint_name_only, tool_name, registered_tools) { let db = match self.check_lint_name(lint_name_only, tool_name, registered_tools) {
CheckLintNameResult::Ok(_) => None, CheckLintNameResult::Ok(_) => None,
@ -339,7 +340,7 @@ impl LintStore {
err.help(&format!("did you mean: `{}`", suggestion)); err.help(&format!("did you mean: `{}`", suggestion));
} }
Some(err) Some(err.forget_guarantee())
} }
CheckLintNameResult::Tool(result) => match result { CheckLintNameResult::Tool(result) => match result {
Err((Some(_), new_name)) => Some(sess.struct_warn(&format!( Err((Some(_), new_name)) => Some(sess.struct_warn(&format!(
@ -350,13 +351,16 @@ impl LintStore {
))), ))),
_ => None, _ => None,
}, },
CheckLintNameResult::NoTool => Some(struct_span_err!( CheckLintNameResult::NoTool => Some(
sess, struct_span_err!(
DUMMY_SP, sess,
E0602, DUMMY_SP,
"unknown lint tool: `{}`", E0602,
tool_name.unwrap() "unknown lint tool: `{}`",
)), tool_name.unwrap()
)
.forget_guarantee(),
),
}; };
if let Some(mut db) = db { if let Some(mut db) = db {

View File

@ -3,7 +3,7 @@ use crate::late::unerased_lint_store;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_errors::{struct_span_err, Applicability, Diagnostic};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::{intravisit, HirId}; use rustc_hir::{intravisit, HirId};
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
@ -150,29 +150,28 @@ impl<'s> LintLevelsBuilder<'s> {
fcw_warning, specs, old_src, id_name fcw_warning, specs, old_src, id_name
); );
let decorate_diag_builder = |mut diag_builder: DiagnosticBuilder<'_>| { let decorate_diag = |diag: &mut Diagnostic| {
diag_builder.span_label(src.span(), "overruled by previous forbid"); diag.span_label(src.span(), "overruled by previous forbid");
match old_src { match old_src {
LintLevelSource::Default => { LintLevelSource::Default => {
diag_builder.note(&format!( diag.note(&format!(
"`forbid` lint level is the default for {}", "`forbid` lint level is the default for {}",
id.to_string() id.to_string()
)); ));
} }
LintLevelSource::Node(_, forbid_source_span, reason) => { LintLevelSource::Node(_, forbid_source_span, reason) => {
diag_builder.span_label(forbid_source_span, "`forbid` level set here"); diag.span_label(forbid_source_span, "`forbid` level set here");
if let Some(rationale) = reason { if let Some(rationale) = reason {
diag_builder.note(rationale.as_str()); diag.note(rationale.as_str());
} }
} }
LintLevelSource::CommandLine(_, _) => { LintLevelSource::CommandLine(_, _) => {
diag_builder.note("`forbid` lint level was set on command line"); diag.note("`forbid` lint level was set on command line");
} }
} }
diag_builder.emit();
}; };
if !fcw_warning { if !fcw_warning {
let diag_builder = struct_span_err!( let mut diag_builder = struct_span_err!(
self.sess, self.sess,
src.span(), src.span(),
E0453, E0453,
@ -180,18 +179,20 @@ impl<'s> LintLevelsBuilder<'s> {
level.as_str(), level.as_str(),
src.name(), src.name(),
); );
decorate_diag_builder(diag_builder); decorate_diag(&mut diag_builder);
diag_builder.emit();
} else { } else {
self.struct_lint( self.struct_lint(
FORBIDDEN_LINT_GROUPS, FORBIDDEN_LINT_GROUPS,
Some(src.span().into()), Some(src.span().into()),
|diag_builder| { |diag_builder| {
let diag_builder = diag_builder.build(&format!( let mut diag_builder = diag_builder.build(&format!(
"{}({}) incompatible with previous forbid", "{}({}) incompatible with previous forbid",
level.as_str(), level.as_str(),
src.name(), src.name(),
)); ));
decorate_diag_builder(diag_builder); decorate_diag(&mut diag_builder);
diag_builder.emit();
}, },
); );
} }

View File

@ -232,7 +232,7 @@ impl<'a> SessionDiagnosticDerive<'a> {
fn into_diagnostic( fn into_diagnostic(
self, self,
#sess: &'__session_diagnostic_sess rustc_session::Session #sess: &'__session_diagnostic_sess rustc_session::Session
) -> rustc_errors::DiagnosticBuilder<'__session_diagnostic_sess> { ) -> rustc_errors::DiagnosticBuilder<'__session_diagnostic_sess, rustc_errors::ErrorReported> {
#implementation #implementation
} }
} }

View File

@ -243,7 +243,9 @@ impl Collector<'_> {
if matches!(lib.kind, NativeLibKind::Framework { .. }) && !is_osx { if matches!(lib.kind, NativeLibKind::Framework { .. }) && !is_osx {
let msg = "native frameworks are only available on macOS targets"; let msg = "native frameworks are only available on macOS targets";
match span { match span {
Some(span) => struct_span_err!(self.tcx.sess, span, E0455, "{}", msg).emit(), Some(span) => {
struct_span_err!(self.tcx.sess, span, E0455, "{}", msg).emit();
}
None => self.tcx.sess.err(msg), None => self.tcx.sess.err(msg),
} }
} }

View File

@ -186,18 +186,18 @@ impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
} }
} }
pub struct LintDiagnosticBuilder<'a>(DiagnosticBuilder<'a>); pub struct LintDiagnosticBuilder<'a>(DiagnosticBuilder<'a, ()>);
impl<'a> LintDiagnosticBuilder<'a> { impl<'a> LintDiagnosticBuilder<'a> {
/// Return the inner DiagnosticBuilder, first setting the primary message to `msg`. /// Return the inner DiagnosticBuilder, first setting the primary message to `msg`.
pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a> { pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a, ()> {
self.0.set_primary_message(msg); self.0.set_primary_message(msg);
self.0.set_is_lint(); self.0.set_is_lint();
self.0 self.0
} }
/// Create a LintDiagnosticBuilder from some existing DiagnosticBuilder. /// Create a LintDiagnosticBuilder from some existing DiagnosticBuilder.
pub fn new(err: DiagnosticBuilder<'a>) -> LintDiagnosticBuilder<'a> { pub fn new(err: DiagnosticBuilder<'a, ()>) -> LintDiagnosticBuilder<'a> {
LintDiagnosticBuilder(err) LintDiagnosticBuilder(err)
} }
} }

View File

@ -36,7 +36,10 @@ TrivialTypeFoldableAndLiftImpls! {
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>; pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>; pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'tcx> { pub fn struct_error<'tcx>(
tcx: TyCtxtAt<'tcx>,
msg: &str,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg) struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
} }

View File

@ -6,7 +6,9 @@ use super::{PatCtxt, PatternError};
use rustc_arena::TypedArena; use rustc_arena::TypedArena;
use rustc_ast::Mutability; use rustc_ast::Mutability;
use rustc_errors::{error_code, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{
error_code, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorReported,
};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::*; use rustc_hir::def::*;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -36,7 +38,11 @@ crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
visitor.visit_body(tcx.hir().body(body_id)); visitor.visit_body(tcx.hir().body(body_id));
} }
fn create_e0004(sess: &Session, sp: Span, error_message: String) -> DiagnosticBuilder<'_> { fn create_e0004(
sess: &Session,
sp: Span,
error_message: String,
) -> DiagnosticBuilder<'_, ErrorReported> {
struct_span_err!(sess, sp, E0004, "{}", &error_message) struct_span_err!(sess, sp, E0004, "{}", &error_message)
} }

View File

@ -64,7 +64,7 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
place: &Place<'tcx>, place: &Place<'tcx>,
const_item: DefId, const_item: DefId,
location: Location, location: Location,
decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b>) -> DiagnosticBuilder<'b>, decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b>) -> DiagnosticBuilder<'b, ()>,
) { ) {
// Don't lint on borrowing/assigning when a dereference is involved. // Don't lint on borrowing/assigning when a dereference is involved.
// If we 'leave' the temporary via a dereference, we must // If we 'leave' the temporary via a dereference, we must

View File

@ -3,7 +3,9 @@ use rustc_ast::ast::{self, AttrStyle};
use rustc_ast::token::{self, CommentKind, Token, TokenKind}; use rustc_ast::token::{self, CommentKind, Token, TokenKind};
use rustc_ast::tokenstream::{Spacing, TokenStream}; use rustc_ast::tokenstream::{Spacing, TokenStream};
use rustc_ast::util::unicode::contains_text_flow_control_chars; use rustc_ast::util::unicode::contains_text_flow_control_chars;
use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError, PResult}; use rustc_errors::{
error_code, Applicability, DiagnosticBuilder, ErrorReported, FatalError, PResult,
};
use rustc_lexer::unescape::{self, Mode}; use rustc_lexer::unescape::{self, Mode};
use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_lexer::{Base, DocStyle, RawStrError};
use rustc_session::lint::builtin::{ use rustc_session::lint::builtin::{
@ -127,7 +129,7 @@ impl<'a> StringReader<'a> {
to_pos: BytePos, to_pos: BytePos,
m: &str, m: &str,
c: char, c: char,
) -> DiagnosticBuilder<'a> { ) -> DiagnosticBuilder<'a, ErrorReported> {
self.sess self.sess
.span_diagnostic .span_diagnostic
.struct_span_fatal(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c))) .struct_span_fatal(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c)))

View File

@ -144,7 +144,7 @@ pub(crate) fn emit_unescape_error(
c.escape_default().to_string(), c.escape_default().to_string(),
Applicability::MachineApplicable, Applicability::MachineApplicable,
) )
.emit() .emit();
} }
EscapeError::BareCarriageReturn => { EscapeError::BareCarriageReturn => {
let msg = if mode.in_double_quotes() { let msg = if mode.in_double_quotes() {
@ -292,16 +292,18 @@ pub(crate) fn emit_unescape_error(
.span_label(span, "must have at most 6 hex digits") .span_label(span, "must have at most 6 hex digits")
.emit(); .emit();
} }
EscapeError::UnclosedUnicodeEscape => handler EscapeError::UnclosedUnicodeEscape => {
.struct_span_err(span, "unterminated unicode escape") handler
.span_label(span, "missing a closing `}`") .struct_span_err(span, "unterminated unicode escape")
.span_suggestion_verbose( .span_label(span, "missing a closing `}`")
span.shrink_to_hi(), .span_suggestion_verbose(
"terminate the unicode escape", span.shrink_to_hi(),
"}".to_string(), "terminate the unicode escape",
Applicability::MaybeIncorrect, "}".to_string(),
) Applicability::MaybeIncorrect,
.emit(), )
.emit();
}
EscapeError::NoBraceInUnicodeEscape => { EscapeError::NoBraceInUnicodeEscape => {
let msg = "incorrect unicode escape sequence"; let msg = "incorrect unicode escape sequence";
let mut diag = handler.struct_span_err(span, msg); let mut diag = handler.struct_span_err(span, msg);
@ -347,7 +349,7 @@ pub(crate) fn emit_unescape_error(
} }
EscapeError::ZeroChars => { EscapeError::ZeroChars => {
let msg = "empty character literal"; let msg = "empty character literal";
handler.struct_span_err(span, msg).span_label(span, msg).emit() handler.struct_span_err(span, msg).span_label(span, msg).emit();
} }
EscapeError::LoneSlash => { EscapeError::LoneSlash => {
let msg = "invalid trailing slash in literal"; let msg = "invalid trailing slash in literal";

View File

@ -16,7 +16,7 @@ use rustc_ast::{
}; };
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, struct_span_err, Diagnostic}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorReported};
use rustc_errors::{Applicability, DiagnosticBuilder, Handler, PResult}; use rustc_errors::{Applicability, DiagnosticBuilder, Handler, PResult};
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, Ident}; use rustc_span::symbol::{kw, Ident};
@ -53,7 +53,11 @@ pub enum Error {
} }
impl Error { impl Error {
fn span_err(self, sp: impl Into<MultiSpan>, handler: &Handler) -> DiagnosticBuilder<'_> { fn span_err(
self,
sp: impl Into<MultiSpan>,
handler: &Handler,
) -> DiagnosticBuilder<'_, ErrorReported> {
match self { match self {
Error::UselessDocComment => { Error::UselessDocComment => {
let mut err = struct_span_err!( let mut err = struct_span_err!(
@ -151,11 +155,19 @@ impl AttemptLocalParseRecovery {
} }
impl<'a> Parser<'a> { impl<'a> Parser<'a> {
pub(super) fn span_err<S: Into<MultiSpan>>(&self, sp: S, err: Error) -> DiagnosticBuilder<'a> { pub(super) fn span_err<S: Into<MultiSpan>>(
&self,
sp: S,
err: Error,
) -> DiagnosticBuilder<'a, ErrorReported> {
err.span_err(sp, self.diagnostic()) err.span_err(sp, self.diagnostic())
} }
pub fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
m: &str,
) -> DiagnosticBuilder<'a, ErrorReported> {
self.sess.span_diagnostic.struct_span_err(sp, m) self.sess.span_diagnostic.struct_span_err(sp, m)
} }
@ -171,7 +183,7 @@ impl<'a> Parser<'a> {
self.sess.source_map().span_to_snippet(span) self.sess.source_map().span_to_snippet(span)
} }
pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a> { pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a, ErrorReported> {
let mut err = self.struct_span_err( let mut err = self.struct_span_err(
self.token.span, self.token.span,
&format!("expected identifier, found {}", super::token_descr(&self.token)), &format!("expected identifier, found {}", super::token_descr(&self.token)),
@ -717,7 +729,7 @@ impl<'a> Parser<'a> {
/// encounter a parse error when encountering the first `,`. /// encounter a parse error when encountering the first `,`.
pub(super) fn check_mistyped_turbofish_with_multiple_type_params( pub(super) fn check_mistyped_turbofish_with_multiple_type_params(
&mut self, &mut self,
mut e: DiagnosticBuilder<'a>, mut e: DiagnosticBuilder<'a, ErrorReported>,
expr: &mut P<Expr>, expr: &mut P<Expr>,
) -> PResult<'a, ()> { ) -> PResult<'a, ()> {
if let ExprKind::Binary(binop, _, _) = &expr.kind { if let ExprKind::Binary(binop, _, _) = &expr.kind {
@ -1439,7 +1451,7 @@ impl<'a> Parser<'a> {
pub(super) fn recover_closing_delimiter( pub(super) fn recover_closing_delimiter(
&mut self, &mut self,
tokens: &[TokenKind], tokens: &[TokenKind],
mut err: DiagnosticBuilder<'a>, mut err: DiagnosticBuilder<'a, ErrorReported>,
) -> PResult<'a, bool> { ) -> PResult<'a, bool> {
let mut pos = None; let mut pos = None;
// We want to use the last closing delim that would apply. // We want to use the last closing delim that would apply.
@ -1810,7 +1822,7 @@ impl<'a> Parser<'a> {
} }
} }
pub(super) fn expected_expression_found(&self) -> DiagnosticBuilder<'a> { pub(super) fn expected_expression_found(&self) -> DiagnosticBuilder<'a, ErrorReported> {
let (span, msg) = match (&self.token.kind, self.subparser_name) { let (span, msg) = match (&self.token.kind, self.subparser_name) {
(&token::Eof, Some(origin)) => { (&token::Eof, Some(origin)) => {
let sp = self.sess.source_map().next_point(self.prev_token.span); let sp = self.sess.source_map().next_point(self.prev_token.span);
@ -2016,7 +2028,7 @@ impl<'a> Parser<'a> {
pub fn recover_const_arg( pub fn recover_const_arg(
&mut self, &mut self,
start: Span, start: Span,
mut err: DiagnosticBuilder<'a>, mut err: DiagnosticBuilder<'a, ErrorReported>,
) -> PResult<'a, GenericArg> { ) -> PResult<'a, GenericArg> {
let is_op = AssocOp::from_token(&self.token) let is_op = AssocOp::from_token(&self.token)
.and_then(|op| { .and_then(|op| {
@ -2096,7 +2108,7 @@ impl<'a> Parser<'a> {
pub(super) fn incorrect_move_async_order_found( pub(super) fn incorrect_move_async_order_found(
&self, &self,
move_async_span: Span, move_async_span: Span,
) -> DiagnosticBuilder<'a> { ) -> DiagnosticBuilder<'a, ErrorReported> {
let mut err = let mut err =
self.struct_span_err(move_async_span, "the order of `move` and `async` is incorrect"); self.struct_span_err(move_async_span, "the order of `move` and `async` is incorrect");
err.span_suggestion_verbose( err.span_suggestion_verbose(

View File

@ -17,7 +17,7 @@ use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, Lit, UnOp
use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind}; use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, PResult}; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported, PResult};
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_span::edition::LATEST_STABLE_EDITION; use rustc_span::edition::LATEST_STABLE_EDITION;
@ -1167,7 +1167,9 @@ impl<'a> Parser<'a> {
return Some(self.mk_expr_err(span)); return Some(self.mk_expr_err(span));
} }
Ok(_) => {} Ok(_) => {}
Err(mut err) => err.emit(), Err(mut err) => {
err.emit();
}
} }
} }
_ => {} _ => {}
@ -1819,6 +1821,7 @@ impl<'a> Parser<'a> {
err err
} else { } else {
self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind)) self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
.forget_guarantee()
}; };
err.span_label(sp, format!("invalid suffix `{}`", suf)); err.span_label(sp, format!("invalid suffix `{}`", suf));
err.emit(); err.emit();
@ -2100,9 +2103,9 @@ impl<'a> Parser<'a> {
fn error_missing_if_then_block( fn error_missing_if_then_block(
&self, &self,
if_span: Span, if_span: Span,
err: Option<DiagnosticBuilder<'a>>, err: Option<DiagnosticBuilder<'a, ErrorReported>>,
binop_span: Option<Span>, binop_span: Option<Span>,
) -> DiagnosticBuilder<'a> { ) -> DiagnosticBuilder<'a, ErrorReported> {
let msg = "this `if` expression has a condition, but no block"; let msg = "this `if` expression has a condition, but no block";
let mut err = if let Some(mut err) = err { let mut err = if let Some(mut err) = err {

View File

@ -13,7 +13,7 @@ use rustc_ast::{EnumDef, FieldDef, Generics, TraitRef, Ty, TyKind, Variant, Vari
use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind}; use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
use rustc_ast::{MacArgs, MacCall, MacDelimiter}; use rustc_ast::{MacArgs, MacCall, MacDelimiter};
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_errors::{struct_span_err, Applicability, PResult, StashKey}; use rustc_errors::{struct_span_err, Applicability, ErrorReported, PResult, StashKey};
use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; use rustc_span::edition::{Edition, LATEST_STABLE_EDITION};
use rustc_span::lev_distance::lev_distance; use rustc_span::lev_distance::lev_distance;
use rustc_span::source_map::{self, Span}; use rustc_span::source_map::{self, Span};
@ -801,7 +801,7 @@ impl<'a> Parser<'a> {
before_where_clause_span: Span, before_where_clause_span: Span,
after_predicates: &[WherePredicate], after_predicates: &[WherePredicate],
after_where_clause_span: Span, after_where_clause_span: Span,
) { ) -> ErrorReported {
let mut err = let mut err =
self.struct_span_err(after_where_clause_span, "where clause not allowed here"); self.struct_span_err(after_where_clause_span, "where clause not allowed here");
if !after_predicates.is_empty() { if !after_predicates.is_empty() {

View File

@ -32,7 +32,7 @@ use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_errors::PResult; use rustc_errors::PResult;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported, FatalError};
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
use rustc_span::source_map::{MultiSpan, Span, DUMMY_SP}; use rustc_span::source_map::{MultiSpan, Span, DUMMY_SP};
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
@ -877,7 +877,7 @@ impl<'a> Parser<'a> {
fn recover_missing_braces_around_closure_body( fn recover_missing_braces_around_closure_body(
&mut self, &mut self,
closure_spans: ClosureSpans, closure_spans: ClosureSpans,
mut expect_err: DiagnosticBuilder<'_>, mut expect_err: DiagnosticBuilder<'_, ErrorReported>,
) -> PResult<'a, ()> { ) -> PResult<'a, ()> {
let initial_semicolon = self.token.span; let initial_semicolon = self.token.span;
@ -1429,7 +1429,7 @@ impl<'a> Parser<'a> {
crate fn make_unclosed_delims_error( crate fn make_unclosed_delims_error(
unmatched: UnmatchedBrace, unmatched: UnmatchedBrace,
sess: &ParseSess, sess: &ParseSess,
) -> Option<DiagnosticBuilder<'_>> { ) -> Option<DiagnosticBuilder<'_, ErrorReported>> {
// `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to // `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to
// `unmatched_braces` only for error recovery in the `Parser`. // `unmatched_braces` only for error recovery in the `Parser`.
let found_delim = unmatched.found_delim?; let found_delim = unmatched.found_delim?;

View File

@ -8,7 +8,7 @@ use rustc_ast::{
PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax, PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
}; };
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported, PResult};
use rustc_span::source_map::{respan, Span, Spanned}; use rustc_span::source_map::{respan, Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::symbol::{kw, sym, Ident};
@ -655,7 +655,7 @@ impl<'a> Parser<'a> {
fn fatal_unexpected_non_pat( fn fatal_unexpected_non_pat(
&mut self, &mut self,
err: DiagnosticBuilder<'a>, err: DiagnosticBuilder<'a, ErrorReported>,
expected: Expected, expected: Expected,
) -> PResult<'a, P<Pat>> { ) -> PResult<'a, P<Pat>> {
err.cancel(); err.cancel();
@ -886,7 +886,7 @@ impl<'a> Parser<'a> {
let mut fields = Vec::new(); let mut fields = Vec::new();
let mut etc = false; let mut etc = false;
let mut ate_comma = true; let mut ate_comma = true;
let mut delayed_err: Option<DiagnosticBuilder<'a>> = None; let mut delayed_err: Option<DiagnosticBuilder<'a, ErrorReported>> = None;
let mut etc_span = None; let mut etc_span = None;
while self.token != token::CloseDelim(token::Brace) { while self.token != token::CloseDelim(token::Brace) {

View File

@ -18,7 +18,7 @@ use rustc_ast::{
}; };
use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt}; use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt};
use rustc_ast::{StmtKind, DUMMY_NODE_ID}; use rustc_ast::{StmtKind, DUMMY_NODE_ID};
use rustc_errors::{Applicability, DiagnosticBuilder, PResult}; use rustc_errors::{Applicability, DiagnosticBuilder, ErrorReported, PResult};
use rustc_span::source_map::{BytePos, Span}; use rustc_span::source_map::{BytePos, Span};
use rustc_span::symbol::{kw, sym}; use rustc_span::symbol::{kw, sym};
@ -414,7 +414,10 @@ impl<'a> Parser<'a> {
Ok(block) Ok(block)
} }
fn error_block_no_opening_brace_msg(&mut self, msg: &str) -> DiagnosticBuilder<'a> { fn error_block_no_opening_brace_msg(
&mut self,
msg: &str,
) -> DiagnosticBuilder<'a, ErrorReported> {
let sp = self.token.span; let sp = self.token.span;
let mut e = self.struct_span_err(sp, msg); let mut e = self.struct_span_err(sp, msg);
let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon; let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon;

View File

@ -345,7 +345,8 @@ impl<'a> Parser<'a> {
let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()); let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus());
let bounds = self.parse_generic_bounds_common(allow_plus, None)?; let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
if lt_no_plus { if lt_no_plus {
self.struct_span_err(lo, "lifetime in trait object type must be followed by `+`").emit() self.struct_span_err(lo, "lifetime in trait object type must be followed by `+`")
.emit();
} }
Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None)) Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
} }

View File

@ -2095,7 +2095,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
rustc_errors::Applicability::MachineApplicable, rustc_errors::Applicability::MachineApplicable,
); );
} }
err.emit() err.emit();
} }
} }
} }

View File

@ -219,7 +219,9 @@ impl<'tcx> CheckConstVisitor<'tcx> {
required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect(); required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect();
match missing_gates.as_slice() { match missing_gates.as_slice() {
[] => struct_span_err!(tcx.sess, span, E0744, "{}", msg).emit(), [] => {
struct_span_err!(tcx.sess, span, E0744, "{}", msg).emit();
}
[missing_primary, ref missing_secondary @ ..] => { [missing_primary, ref missing_secondary @ ..] => {
let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, &msg); let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, &msg);

View File

@ -118,7 +118,7 @@ impl<'tcx> ExprVisitor<'tcx> {
err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from))) err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from)))
.note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to))); .note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to)));
} }
err.emit() err.emit();
} }
fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool { fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool {

View File

@ -7,7 +7,7 @@ use crate::query::caches::QueryCache;
use crate::query::{QueryCacheStore, QueryContext, QueryState}; use crate::query::{QueryCacheStore, QueryContext, QueryState};
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
use rustc_errors::DiagnosticBuilder; use rustc_errors::{DiagnosticBuilder, ErrorReported};
use std::fmt::Debug; use std::fmt::Debug;
use std::hash::Hash; use std::hash::Hash;
@ -27,7 +27,7 @@ pub struct QueryVtable<CTX: QueryContext, K, V> {
pub compute: fn(CTX::DepContext, K) -> V, pub compute: fn(CTX::DepContext, K) -> V,
pub hash_result: Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>, pub hash_result: Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>,
pub handle_cycle_error: fn(CTX, DiagnosticBuilder<'_>) -> V, pub handle_cycle_error: fn(CTX, DiagnosticBuilder<'_, ErrorReported>) -> V,
pub try_load_from_disk: Option<fn(CTX, SerializedDepNodeIndex) -> Option<V>>, pub try_load_from_disk: Option<fn(CTX, SerializedDepNodeIndex) -> Option<V>>,
} }

View File

@ -4,7 +4,7 @@ use crate::query::{QueryContext, QueryStackFrame};
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, Handler, Level}; use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, ErrorReported, Handler, Level};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::Span; use rustc_span::Span;
@ -530,7 +530,7 @@ pub fn deadlock<CTX: QueryContext>(tcx: CTX, registry: &rayon_core::Registry) {
pub(crate) fn report_cycle<'a>( pub(crate) fn report_cycle<'a>(
sess: &'a Session, sess: &'a Session,
CycleError { usage, cycle: stack }: CycleError, CycleError { usage, cycle: stack }: CycleError,
) -> DiagnosticBuilder<'a> { ) -> DiagnosticBuilder<'a, ErrorReported> {
assert!(!stack.is_empty()); assert!(!stack.is_empty());
let fix_span = |span: Span, query: &QueryStackFrame| { let fix_span = |span: Span, query: &QueryStackFrame| {

View File

@ -14,7 +14,7 @@ use rustc_data_structures::profiling::TimingGuard;
use rustc_data_structures::sharded::{get_shard_index_by_hash, Sharded}; use rustc_data_structures::sharded::{get_shard_index_by_hash, Sharded};
use rustc_data_structures::sync::{Lock, LockGuard}; use rustc_data_structures::sync::{Lock, LockGuard};
use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::{DiagnosticBuilder, FatalError}; use rustc_errors::{DiagnosticBuilder, ErrorReported, FatalError};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use std::cell::Cell; use std::cell::Cell;
@ -143,7 +143,7 @@ where
fn mk_cycle<CTX, V, R>( fn mk_cycle<CTX, V, R>(
tcx: CTX, tcx: CTX,
error: CycleError, error: CycleError,
handle_cycle_error: fn(CTX, DiagnosticBuilder<'_>) -> V, handle_cycle_error: fn(CTX, DiagnosticBuilder<'_, ErrorReported>) -> V,
cache: &dyn crate::query::QueryStorage<Value = V, Stored = R>, cache: &dyn crate::query::QueryStorage<Value = V, Stored = R>,
) -> R ) -> R
where where

View File

@ -1068,8 +1068,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
.emit(); .emit();
} }
} }
let ill_formed = let ill_formed = |span| {
|span| struct_span_err!(self.r.session, span, E0466, "bad macro import").emit(); struct_span_err!(self.r.session, span, E0466, "bad macro import").emit();
};
match attr.meta() { match attr.meta() {
Some(meta) => match meta.kind { Some(meta) => match meta.kind {
MetaItemKind::Word => { MetaItemKind::Word => {

View File

@ -3,7 +3,7 @@ use std::ptr;
use rustc_ast::{self as ast, Path}; use rustc_ast::{self as ast, Path};
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{struct_span_err, Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_feature::BUILTIN_ATTRIBUTES;
use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind};
@ -110,7 +110,7 @@ impl<'a> Resolver<'a> {
&self, &self,
span: Span, span: Span,
resolution_error: ResolutionError<'_>, resolution_error: ResolutionError<'_>,
) -> DiagnosticBuilder<'_> { ) -> DiagnosticBuilder<'_, ErrorReported> {
match resolution_error { match resolution_error {
ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => { ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => {
let mut err = struct_span_err!( let mut err = struct_span_err!(
@ -624,7 +624,10 @@ impl<'a> Resolver<'a> {
} }
} }
crate fn report_vis_error(&self, vis_resolution_error: VisResolutionError<'_>) { crate fn report_vis_error(
&self,
vis_resolution_error: VisResolutionError<'_>,
) -> ErrorReported {
match vis_resolution_error { match vis_resolution_error {
VisResolutionError::Relative2018(span, path) => { VisResolutionError::Relative2018(span, path) => {
let mut err = self.session.struct_span_err( let mut err = self.session.struct_span_err(

View File

@ -12,7 +12,9 @@ use rustc_ast::{
}; };
use rustc_ast_pretty::pprust::path_segment_to_string; use rustc_ast_pretty::pprust::path_segment_to_string;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorReported,
};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
@ -133,7 +135,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
span: Span, span: Span,
source: PathSource<'_>, source: PathSource<'_>,
res: Option<Res>, res: Option<Res>,
) -> (DiagnosticBuilder<'a>, Vec<ImportSuggestion>) { ) -> (DiagnosticBuilder<'a, ErrorReported>, Vec<ImportSuggestion>) {
let ident_span = path.last().map_or(span, |ident| ident.ident.span); let ident_span = path.last().map_or(span, |ident| ident.ident.span);
let ns = source.namespace(); let ns = source.namespace();
let is_expected = &|res| source.is_expected(res); let is_expected = &|res| source.is_expected(res);
@ -1817,7 +1819,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
&self, &self,
spans: Vec<Span>, spans: Vec<Span>,
count: usize, count: usize,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
struct_span_err!( struct_span_err!(
self.tcx.sess, self.tcx.sess,
spans, spans,

View File

@ -1572,6 +1572,7 @@ fn signal_shadowing_problem(tcx: TyCtxt<'_>, name: Symbol, orig: Original, shado
name, name,
orig.kind.desc() orig.kind.desc()
) )
.forget_guarantee()
} else { } else {
// shadowing involving a label is only a warning, due to issues with // shadowing involving a label is only a warning, due to issues with
// labels and lifetimes not being macro-hygienic. // labels and lifetimes not being macro-hygienic.

View File

@ -40,7 +40,7 @@ use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::intern::Interned; use rustc_data_structures::intern::Interned;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_errors::{struct_span_err, Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind};
use rustc_hir::def::Namespace::*; use rustc_hir::def::Namespace::*;
use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes}; use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
@ -713,7 +713,7 @@ struct PrivacyError<'a> {
} }
struct UseError<'a> { struct UseError<'a> {
err: DiagnosticBuilder<'a>, err: DiagnosticBuilder<'a, ErrorReported>,
/// Candidates which user could `use` to access the missing type. /// Candidates which user could `use` to access the missing type.
candidates: Vec<ImportSuggestion>, candidates: Vec<ImportSuggestion>,
/// The `DefId` of the module to place the use-statements in. /// The `DefId` of the module to place the use-statements in.

View File

@ -7,7 +7,7 @@ use rustc_ast::node_id::NodeId;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{Lock, Lrc}; use rustc_data_structures::sync::{Lock, Lrc};
use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
use rustc_errors::{error_code, Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{error_code, Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
use rustc_span::hygiene::ExpnId; use rustc_span::hygiene::ExpnId;
@ -82,7 +82,7 @@ pub fn feature_err<'a>(
feature: Symbol, feature: Symbol,
span: impl Into<MultiSpan>, span: impl Into<MultiSpan>,
explain: &str, explain: &str,
) -> DiagnosticBuilder<'a> { ) -> DiagnosticBuilder<'a, ErrorReported> {
feature_err_issue(sess, feature, span, GateIssue::Language, explain) feature_err_issue(sess, feature, span, GateIssue::Language, explain)
} }
@ -96,7 +96,7 @@ pub fn feature_err_issue<'a>(
span: impl Into<MultiSpan>, span: impl Into<MultiSpan>,
issue: GateIssue, issue: GateIssue,
explain: &str, explain: &str,
) -> DiagnosticBuilder<'a> { ) -> DiagnosticBuilder<'a, ErrorReported> {
let mut err = sess.span_diagnostic.struct_span_err_with_code(span, explain, error_code!(E0658)); let mut err = sess.span_diagnostic.struct_span_err_with_code(span, explain, error_code!(E0658));
if let Some(n) = find_feature_issue(feature, issue) { if let Some(n) = find_feature_issue(feature, issue) {

View File

@ -221,7 +221,7 @@ enum DiagnosticBuilderMethod {
pub trait SessionDiagnostic<'a> { pub trait SessionDiagnostic<'a> {
/// Write out as a diagnostic out of `sess`. /// Write out as a diagnostic out of `sess`.
#[must_use] #[must_use]
fn into_diagnostic(self, sess: &'a Session) -> DiagnosticBuilder<'a>; fn into_diagnostic(self, sess: &'a Session) -> DiagnosticBuilder<'a, ErrorReported>;
} }
/// Diagnostic message ID, used by `Session.one_time_diagnostics` to avoid /// Diagnostic message ID, used by `Session.one_time_diagnostics` to avoid
@ -303,7 +303,11 @@ impl Session {
self.crate_types.set(crate_types).expect("`crate_types` was initialized twice") self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
} }
pub fn struct_span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_span_warn<S: Into<MultiSpan>>(
&self,
sp: S,
msg: &str,
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_span_warn(sp, msg) self.diagnostic().struct_span_warn(sp, msg)
} }
pub fn struct_span_warn_with_code<S: Into<MultiSpan>>( pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
@ -311,19 +315,27 @@ impl Session {
sp: S, sp: S,
msg: &str, msg: &str,
code: DiagnosticId, code: DiagnosticId,
) -> DiagnosticBuilder<'_> { ) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_span_warn_with_code(sp, msg, code) self.diagnostic().struct_span_warn_with_code(sp, msg, code)
} }
pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_warn(msg) self.diagnostic().struct_warn(msg)
} }
pub fn struct_span_allow<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_span_allow<S: Into<MultiSpan>>(
&self,
sp: S,
msg: &str,
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_span_allow(sp, msg) self.diagnostic().struct_span_allow(sp, msg)
} }
pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_allow(msg) self.diagnostic().struct_allow(msg)
} }
pub fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
msg: &str,
) -> DiagnosticBuilder<'_, ErrorReported> {
self.diagnostic().struct_span_err(sp, msg) self.diagnostic().struct_span_err(sp, msg)
} }
pub fn struct_span_err_with_code<S: Into<MultiSpan>>( pub fn struct_span_err_with_code<S: Into<MultiSpan>>(
@ -331,17 +343,25 @@ impl Session {
sp: S, sp: S,
msg: &str, msg: &str,
code: DiagnosticId, code: DiagnosticId,
) -> DiagnosticBuilder<'_> { ) -> DiagnosticBuilder<'_, ErrorReported> {
self.diagnostic().struct_span_err_with_code(sp, msg, code) self.diagnostic().struct_span_err_with_code(sp, msg, code)
} }
// FIXME: This method should be removed (every error should have an associated error code). // FIXME: This method should be removed (every error should have an associated error code).
pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorReported> {
self.diagnostic().struct_err(msg) self.diagnostic().struct_err(msg)
} }
pub fn struct_err_with_code(&self, msg: &str, code: DiagnosticId) -> DiagnosticBuilder<'_> { pub fn struct_err_with_code(
&self,
msg: &str,
code: DiagnosticId,
) -> DiagnosticBuilder<'_, ErrorReported> {
self.diagnostic().struct_err_with_code(msg, code) self.diagnostic().struct_err_with_code(msg, code)
} }
pub fn struct_span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_span_fatal<S: Into<MultiSpan>>(
&self,
sp: S,
msg: &str,
) -> DiagnosticBuilder<'_, ErrorReported> {
self.diagnostic().struct_span_fatal(sp, msg) self.diagnostic().struct_span_fatal(sp, msg)
} }
pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>( pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
@ -349,10 +369,10 @@ impl Session {
sp: S, sp: S,
msg: &str, msg: &str,
code: DiagnosticId, code: DiagnosticId,
) -> DiagnosticBuilder<'_> { ) -> DiagnosticBuilder<'_, ErrorReported> {
self.diagnostic().struct_span_fatal_with_code(sp, msg, code) self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
} }
pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorReported> {
self.diagnostic().struct_fatal(msg) self.diagnostic().struct_fatal(msg)
} }
@ -386,7 +406,7 @@ impl Session {
pub fn err(&self, msg: &str) { pub fn err(&self, msg: &str) {
self.diagnostic().err(msg) self.diagnostic().err(msg)
} }
pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) { pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorReported {
err.into_diagnostic(self).emit() err.into_diagnostic(self).emit()
} }
#[inline] #[inline]
@ -457,7 +477,7 @@ impl Session {
pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.diagnostic().span_note_without_error(sp, msg) self.diagnostic().span_note_without_error(sp, msg)
} }
pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_note_without_error(msg) self.diagnostic().struct_note_without_error(msg)
} }

View File

@ -102,7 +102,7 @@ pub trait InferCtxtExt<'tcx> {
expected_args: Vec<ArgKind>, expected_args: Vec<ArgKind>,
found_args: Vec<ArgKind>, found_args: Vec<ArgKind>,
is_closure: bool, is_closure: bool,
) -> DiagnosticBuilder<'tcx>; ) -> DiagnosticBuilder<'tcx, ErrorReported>;
} }
impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
@ -1019,7 +1019,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
expected_args: Vec<ArgKind>, expected_args: Vec<ArgKind>,
found_args: Vec<ArgKind>, found_args: Vec<ArgKind>,
is_closure: bool, is_closure: bool,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let kind = if is_closure { "closure" } else { "function" }; let kind = if is_closure { "closure" } else { "function" };
let args_str = |arguments: &[ArgKind], other: &[ArgKind]| { let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {

View File

@ -10,7 +10,8 @@ use crate::traits::normalize_projection_type;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{ use rustc_errors::{
error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, Style, error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder,
ErrorReported, Style,
}; };
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
@ -122,7 +123,7 @@ pub trait InferCtxtExt<'tcx> {
found_span: Option<Span>, found_span: Option<Span>,
expected_ref: ty::PolyTraitRef<'tcx>, expected_ref: ty::PolyTraitRef<'tcx>,
found: ty::PolyTraitRef<'tcx>, found: ty::PolyTraitRef<'tcx>,
) -> DiagnosticBuilder<'tcx>; ) -> DiagnosticBuilder<'tcx, ErrorReported>;
fn suggest_fully_qualified_path( fn suggest_fully_qualified_path(
&self, &self,
@ -1271,7 +1272,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
found_span: Option<Span>, found_span: Option<Span>,
expected_ref: ty::PolyTraitRef<'tcx>, expected_ref: ty::PolyTraitRef<'tcx>,
found: ty::PolyTraitRef<'tcx>, found: ty::PolyTraitRef<'tcx>,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
crate fn build_fn_sig_string<'tcx>( crate fn build_fn_sig_string<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,

View File

@ -450,7 +450,7 @@ fn report_conflicting_impls(
sg.has_errored = true; sg.has_errored = true;
if overlap.with_impl.is_local() || !tcx.orphan_check_crate(()).contains(&impl_def_id) { if overlap.with_impl.is_local() || !tcx.orphan_check_crate(()).contains(&impl_def_id) {
let err = struct_span_err!(tcx.sess, impl_span, E0119, ""); let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
decorate(LintDiagnosticBuilder::new(err)); decorate(LintDiagnosticBuilder::new(err.forget_guarantee()));
} else { } else {
tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check"); tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check");
} }

View File

@ -15,7 +15,7 @@ use crate::middle::resolve_lifetime as rl;
use crate::require_c_abi_if_c_variadic; use crate::require_c_abi_if_c_variadic;
use rustc_ast::TraitObjectSyntax; use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{struct_span_err, Applicability, ErrorReported, FatalError}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported, FatalError};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
@ -2618,7 +2618,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&self, &self,
constrained_regions: FxHashSet<ty::BoundRegionKind>, constrained_regions: FxHashSet<ty::BoundRegionKind>,
referenced_regions: FxHashSet<ty::BoundRegionKind>, referenced_regions: FxHashSet<ty::BoundRegionKind>,
generate_err: impl Fn(&str) -> rustc_errors::DiagnosticBuilder<'tcx>, generate_err: impl Fn(&str) -> DiagnosticBuilder<'tcx, ErrorReported>,
) { ) {
for br in referenced_regions.difference(&constrained_regions) { for br in referenced_regions.difference(&constrained_regions) {
let br_name = match *br { let br_name = match *br {

View File

@ -179,7 +179,7 @@ fn make_invalid_casting_error<'a, 'tcx>(
expr_ty: Ty<'tcx>, expr_ty: Ty<'tcx>,
cast_ty: Ty<'tcx>, cast_ty: Ty<'tcx>,
fcx: &FnCtxt<'a, 'tcx>, fcx: &FnCtxt<'a, 'tcx>,
) -> DiagnosticBuilder<'a> { ) -> DiagnosticBuilder<'a, ErrorReported> {
type_error_struct!( type_error_struct!(
sess, sess,
span, span,

View File

@ -37,14 +37,16 @@ pub fn check_wf_new(tcx: TyCtxt<'_>) {
pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
match tcx.sess.target.is_abi_supported(abi) { match tcx.sess.target.is_abi_supported(abi) {
Some(true) => (), Some(true) => (),
Some(false) => struct_span_err!( Some(false) => {
tcx.sess, struct_span_err!(
span, tcx.sess,
E0570, span,
"`{}` is not a supported ABI for the current target", E0570,
abi "`{}` is not a supported ABI for the current target",
) abi
.emit(), )
.emit();
}
None => { None => {
tcx.struct_span_lint_hir(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| { tcx.struct_span_lint_hir(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
lint.build("use of calling convention not supported on this target").emit() lint.build("use of calling convention not supported on this target").emit()
@ -60,7 +62,7 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab
E0781, E0781,
"the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers"
) )
.emit() .emit();
} }
} }

View File

@ -37,7 +37,7 @@
use crate::astconv::AstConv; use crate::astconv::AstConv;
use crate::check::FnCtxt; use crate::check::FnCtxt;
use rustc_errors::{struct_span_err, Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@ -1520,7 +1520,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
fcx: &FnCtxt<'a, 'tcx>, fcx: &FnCtxt<'a, 'tcx>,
id: hir::HirId, id: hir::HirId,
expression: Option<(&'tcx hir::Expr<'tcx>, hir::HirId)>, expression: Option<(&'tcx hir::Expr<'tcx>, hir::HirId)>,
) -> DiagnosticBuilder<'a> { ) -> DiagnosticBuilder<'a, ErrorReported> {
let mut err = fcx.report_mismatched_types(cause, expected, found, ty_err); let mut err = fcx.report_mismatched_types(cause, expected, found, ty_err);
let mut pointing_at_return_type = false; let mut pointing_at_return_type = false;

View File

@ -4,7 +4,7 @@ use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::ObligationCause; use rustc_trait_selection::traits::ObligationCause;
use rustc_ast::util::parser::PREC_POSTFIX; use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::{is_range_literal, Node}; use rustc_hir::{is_range_literal, Node};
@ -57,7 +57,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sp: Span, sp: Span,
expected: Ty<'tcx>, expected: Ty<'tcx>,
actual: Ty<'tcx>, actual: Ty<'tcx>,
) -> Option<DiagnosticBuilder<'tcx>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
self.demand_suptype_with_origin(&self.misc(sp), expected, actual) self.demand_suptype_with_origin(&self.misc(sp), expected, actual)
} }
@ -67,7 +67,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
cause: &ObligationCause<'tcx>, cause: &ObligationCause<'tcx>,
expected: Ty<'tcx>, expected: Ty<'tcx>,
actual: Ty<'tcx>, actual: Ty<'tcx>,
) -> Option<DiagnosticBuilder<'tcx>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
match self.at(cause, self.param_env).sup(expected, actual) { match self.at(cause, self.param_env).sup(expected, actual) {
Ok(InferOk { obligations, value: () }) => { Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations); self.register_predicates(obligations);
@ -88,7 +88,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sp: Span, sp: Span,
expected: Ty<'tcx>, expected: Ty<'tcx>,
actual: Ty<'tcx>, actual: Ty<'tcx>,
) -> Option<DiagnosticBuilder<'tcx>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
self.demand_eqtype_with_origin(&self.misc(sp), expected, actual) self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
} }
@ -97,7 +97,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
cause: &ObligationCause<'tcx>, cause: &ObligationCause<'tcx>,
expected: Ty<'tcx>, expected: Ty<'tcx>,
actual: Ty<'tcx>, actual: Ty<'tcx>,
) -> Option<DiagnosticBuilder<'tcx>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
match self.at(cause, self.param_env).eq(expected, actual) { match self.at(cause, self.param_env).eq(expected, actual) {
Ok(InferOk { obligations, value: () }) => { Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations); self.register_predicates(obligations);
@ -134,7 +134,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>, expected: Ty<'tcx>,
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
allow_two_phase: AllowTwoPhase, allow_two_phase: AllowTwoPhase,
) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) { ) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx, ErrorReported>>) {
let expected = self.resolve_vars_with_obligations(expected); let expected = self.resolve_vars_with_obligations(expected);
let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase, None) { let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase, None) {

View File

@ -486,7 +486,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.map_or(false, |x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_)))) .map_or(false, |x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
}); });
if !is_named { if !is_named {
self.tcx.sess.emit_err(AddressOfTemporaryTaken { span: oprnd.span }) self.tcx.sess.emit_err(AddressOfTemporaryTaken { span: oprnd.span });
} }
} }
@ -1470,14 +1470,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.register_predicates(obligations) self.register_predicates(obligations)
} }
// FIXME: Need better diagnostics for `FieldMisMatch` error // FIXME: Need better diagnostics for `FieldMisMatch` error
Err(_) => self Err(_) => {
.report_mismatched_types( self.report_mismatched_types(
&cause, &cause,
target_ty, target_ty,
fru_ty, fru_ty,
FieldMisMatch(variant.name, ident.name), FieldMisMatch(variant.name, ident.name),
) )
.emit(), .emit();
}
} }
} }
fru_ty fru_ty
@ -1485,22 +1486,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.collect() .collect()
} }
_ => { _ => {
return self self.report_mismatched_types(
.report_mismatched_types( &self.misc(base_expr.span),
&self.misc(base_expr.span), adt_ty,
adt_ty, base_ty,
base_ty, Sorts(ExpectedFound::new(true, adt_ty, base_ty)),
Sorts(ExpectedFound::new(true, adt_ty, base_ty)), )
) .emit();
.emit(); return;
} }
} }
} }
_ => { _ => {
return self self.tcx
.tcx
.sess .sess
.emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span }); .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span });
return;
} }
} }
} else { } else {
@ -1529,10 +1530,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}) })
.collect(), .collect(),
_ => { _ => {
return self self.tcx
.tcx
.sess .sess
.emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span }); .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span });
return;
} }
} }
}; };
@ -2213,7 +2214,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
field: Ident, field: Ident,
expr_t: Ty<'tcx>, expr_t: Ty<'tcx>,
id: HirId, id: HirId,
) -> DiagnosticBuilder<'_> { ) -> DiagnosticBuilder<'_, ErrorReported> {
let span = field.span; let span = field.span;
debug!("no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})", span, field, expr_t); debug!("no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})", span, field, expr_t);

View File

@ -460,7 +460,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn variadic_error<'tcx>(sess: &Session, span: Span, ty: Ty<'tcx>, cast_ty: &str) { fn variadic_error<'tcx>(sess: &Session, span: Span, ty: Ty<'tcx>, cast_ty: &str) {
use crate::structured_errors::MissingCastForVariadicArg; use crate::structured_errors::MissingCastForVariadicArg;
MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit() MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit();
} }
for arg in provided_args.iter().skip(expected_arg_count) { for arg in provided_args.iter().skip(expected_arg_count) {

View File

@ -3,7 +3,9 @@
use crate::check::FnCtxt; use crate::check::FnCtxt;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorReported,
};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
@ -91,7 +93,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
source: SelfSource<'tcx>, source: SelfSource<'tcx>,
error: MethodError<'tcx>, error: MethodError<'tcx>,
args: Option<&'tcx [hir::Expr<'tcx>]>, args: Option<&'tcx [hir::Expr<'tcx>]>,
) -> Option<DiagnosticBuilder<'_>> { ) -> Option<DiagnosticBuilder<'_, ErrorReported>> {
// Avoid suggestions when we don't know what's going on. // Avoid suggestions when we don't know what's going on.
if rcvr_ty.references_error() { if rcvr_ty.references_error() {
return None; return None;

View File

@ -2,7 +2,9 @@ use crate::check::FnCtxt;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorReported,
};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::pat_util::EnumerateAndAdjustIterator;
@ -98,7 +100,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
expected: Ty<'tcx>, expected: Ty<'tcx>,
actual: Ty<'tcx>, actual: Ty<'tcx>,
ti: TopInfo<'tcx>, ti: TopInfo<'tcx>,
) -> Option<DiagnosticBuilder<'tcx>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual) self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)
} }
@ -817,7 +819,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn emit_bad_pat_path<'b>( fn emit_bad_pat_path<'b>(
&self, &self,
mut e: DiagnosticBuilder<'_>, mut e: DiagnosticBuilder<'_, ErrorReported>,
pat_span: Span, pat_span: Span,
res: Res, res: Res,
pat_res: Res, pat_res: Res,
@ -1368,7 +1370,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
variant: &VariantDef, variant: &VariantDef,
pat: &'_ Pat<'_>, pat: &'_ Pat<'_>,
fields: &[hir::PatField<'_>], fields: &[hir::PatField<'_>],
) -> Option<DiagnosticBuilder<'_>> { ) -> Option<DiagnosticBuilder<'_, ErrorReported>> {
// if this is a tuple struct, then all field names will be numbers // if this is a tuple struct, then all field names will be numbers
// so if any fields in a struct pattern use shorthand syntax, they will // so if any fields in a struct pattern use shorthand syntax, they will
// be invalid identifiers (for example, Foo { 0, 1 }). // be invalid identifiers (for example, Foo { 0, 1 }).
@ -1441,7 +1443,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
inexistent_fields: &[Ident], inexistent_fields: &[Ident],
unmentioned_fields: &mut Vec<(&ty::FieldDef, Ident)>, unmentioned_fields: &mut Vec<(&ty::FieldDef, Ident)>,
variant: &ty::VariantDef, variant: &ty::VariantDef,
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let tcx = self.tcx; let tcx = self.tcx;
let (field_names, t, plural) = if inexistent_fields.len() == 1 { let (field_names, t, plural) = if inexistent_fields.len() == 1 {
(format!("a field named `{}`", inexistent_fields[0]), "this", "") (format!("a field named `{}`", inexistent_fields[0]), "this", "")
@ -1537,7 +1539,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat: &Pat<'_>, pat: &Pat<'_>,
fields: &'tcx [hir::PatField<'tcx>], fields: &'tcx [hir::PatField<'tcx>],
variant: &ty::VariantDef, variant: &ty::VariantDef,
) -> Option<DiagnosticBuilder<'tcx>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorReported>> {
if let (CtorKind::Fn, PatKind::Struct(qpath, ..)) = (variant.ctor_kind, &pat.kind) { if let (CtorKind::Fn, PatKind::Struct(qpath, ..)) = (variant.ctor_kind, &pat.kind) {
let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| { let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
s.print_qpath(qpath, false) s.print_qpath(qpath, false)
@ -1619,7 +1621,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self, &self,
pat: &Pat<'_>, pat: &Pat<'_>,
fields: &'tcx [hir::PatField<'tcx>], fields: &'tcx [hir::PatField<'tcx>],
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let mut err = self let mut err = self
.tcx .tcx
.sess .sess
@ -1711,7 +1713,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
unmentioned_fields: &[(&ty::FieldDef, Ident)], unmentioned_fields: &[(&ty::FieldDef, Ident)],
have_inaccessible_fields: bool, have_inaccessible_fields: bool,
fields: &'tcx [hir::PatField<'tcx>], fields: &'tcx [hir::PatField<'tcx>],
) -> DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" }; let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" };
let field_names = if unmentioned_fields.len() == 1 { let field_names = if unmentioned_fields.len() == 1 {
format!("field `{}`{}", unmentioned_fields[0].1, inaccessible) format!("field `{}`{}", unmentioned_fields[0].1, inaccessible)

View File

@ -4,7 +4,7 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit as hir_visit; use rustc_hir::intravisit as hir_visit;
@ -448,7 +448,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
for more information", for more information",
); );
err.emit() err.emit();
} }
} }
} }
@ -843,7 +843,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
"using {} as const generic parameters is forbidden", "using {} as const generic parameters is forbidden",
unsupported_type unsupported_type
), ),
) );
} else { } else {
let mut err = tcx.sess.struct_span_err( let mut err = tcx.sess.struct_span_err(
hir_ty.span, hir_ty.span,
@ -858,7 +858,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
"more complex types are supported with `#![feature(adt_const_params)]`", "more complex types are supported with `#![feature(adt_const_params)]`",
); );
} }
err.emit() err.emit();
} }
}; };
@ -1729,12 +1729,14 @@ fn check_variances_for_type_defn<'tcx>(
match param.name { match param.name {
hir::ParamName::Error => {} hir::ParamName::Error => {}
_ => report_bivariance(tcx, param), _ => {
report_bivariance(tcx, param);
}
} }
} }
} }
fn report_bivariance(tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>) { fn report_bivariance(tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>) -> ErrorReported {
let span = param.span; let span = param.span;
let param_name = param.name.ident().name; let param_name = param.name.ident().name;
let mut err = error_392(tcx, span, param_name); let mut err = error_392(tcx, span, param_name);
@ -1943,7 +1945,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
fn error_392(tcx: TyCtxt<'_>, span: Span, param_name: Symbol) -> DiagnosticBuilder<'_> { fn error_392(
tcx: TyCtxt<'_>,
span: Span,
param_name: Symbol,
) -> DiagnosticBuilder<'_, ErrorReported> {
let mut err = let mut err =
struct_span_err!(tcx.sess, span, E0392, "parameter `{}` is never used", param_name); struct_span_err!(tcx.sess, span, E0392, "parameter `{}` is never used", param_name);
err.span_label(span, "unused parameter"); err.span_label(span, "unused parameter");

View File

@ -93,7 +93,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
for span in fields.iter().map(|f| tcx.def_span(f.did)) { for span in fields.iter().map(|f| tcx.def_span(f.did)) {
err.span_label(span, "this field does not implement `Copy`"); err.span_label(span, "this field does not implement `Copy`");
} }
err.emit() err.emit();
} }
Err(CopyImplementationError::NotAnAdt) => { Err(CopyImplementationError::NotAnAdt) => {
let item = tcx.hir().expect_item(impl_did); let item = tcx.hir().expect_item(impl_did);

View File

@ -159,7 +159,7 @@ fn emit_orphan_check_error<'tcx>(
generics: &hir::Generics<'tcx>, generics: &hir::Generics<'tcx>,
err: traits::OrphanCheckErr<'tcx>, err: traits::OrphanCheckErr<'tcx>,
) -> Result<!, ErrorReported> { ) -> Result<!, ErrorReported> {
match err { Err(match err {
traits::OrphanCheckErr::NonLocalInputType(tys) => { traits::OrphanCheckErr::NonLocalInputType(tys) => {
let mut err = struct_span_err!( let mut err = struct_span_err!(
tcx.sess, tcx.sess,
@ -269,9 +269,7 @@ fn emit_orphan_check_error<'tcx>(
.emit(), .emit(),
} }
} }
} })
Err(ErrorReported)
} }
#[derive(Default)] #[derive(Default)]

View File

@ -26,7 +26,7 @@ use rustc_ast::{MetaItemKind, NestedMetaItem};
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr}; use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_errors::{struct_span_err, Applicability}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
@ -321,7 +321,7 @@ fn bad_placeholder<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
mut spans: Vec<Span>, mut spans: Vec<Span>,
kind: &'static str, kind: &'static str,
) -> rustc_errors::DiagnosticBuilder<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorReported> {
let kind = if kind.ends_with('s') { format!("{}es", kind) } else { format!("{}s", kind) }; let kind = if kind.ends_with('s') { format!("{}es", kind) } else { format!("{}s", kind) };
spans.sort(); spans.sort();
@ -1277,19 +1277,21 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
return None; return None;
} }
Some(item) => tcx Some(item) => {
.sess tcx.sess
.struct_span_err(item.span, "Not a function") .struct_span_err(item.span, "Not a function")
.span_note(attr_span, "required by this annotation") .span_note(attr_span, "required by this annotation")
.note( .note(
"All `#[rustc_must_implement_one_of]` arguments \ "All `#[rustc_must_implement_one_of]` arguments \
must be associated function names", must be associated function names",
) )
.emit(), .emit();
None => tcx }
.sess None => {
.struct_span_err(ident.span, "Function not found in this trait") tcx.sess
.emit(), .struct_span_err(ident.span, "Function not found in this trait")
.emit();
}
} }
Some(()) Some(())

View File

@ -393,13 +393,14 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
tcx.def_path_str(trait_ref.def_id), tcx.def_path_str(trait_ref.def_id),
), ),
) )
.emit() .emit();
} }
} }
_ => tcx _ => {
.sess tcx.sess
.struct_span_err(span, &format!("cannot specialize on `{:?}`", predicate)) .struct_span_err(span, &format!("cannot specialize on `{:?}`", predicate))
.emit(), .emit();
}
} }
} }

View File

@ -6,7 +6,7 @@ pub use self::{
missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*, missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*,
}; };
use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorReported};
use rustc_session::Session; use rustc_session::Session;
pub trait StructuredDiagnostic<'tcx> { pub trait StructuredDiagnostic<'tcx> {
@ -14,7 +14,7 @@ pub trait StructuredDiagnostic<'tcx> {
fn code(&self) -> DiagnosticId; fn code(&self) -> DiagnosticId;
fn diagnostic(&self) -> DiagnosticBuilder<'tcx> { fn diagnostic(&self) -> DiagnosticBuilder<'tcx, ErrorReported> {
let err = self.diagnostic_common(); let err = self.diagnostic_common();
if self.session().teach(&self.code()) { if self.session().teach(&self.code()) {
@ -24,13 +24,19 @@ pub trait StructuredDiagnostic<'tcx> {
} }
} }
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx>; fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorReported>;
fn diagnostic_regular(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> { fn diagnostic_regular(
&self,
err: DiagnosticBuilder<'tcx, ErrorReported>,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
err err
} }
fn diagnostic_extended(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> { fn diagnostic_extended(
&self,
err: DiagnosticBuilder<'tcx, ErrorReported>,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
err err
} }
} }

View File

@ -1,5 +1,5 @@
use crate::structured_errors::StructuredDiagnostic; use crate::structured_errors::StructuredDiagnostic;
use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorReported};
use rustc_middle::ty::{Ty, TypeFoldable}; use rustc_middle::ty::{Ty, TypeFoldable};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::Span; use rustc_span::Span;
@ -20,7 +20,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx> {
rustc_errors::error_code!(E0617) rustc_errors::error_code!(E0617)
} }
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> { fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorReported> {
let mut err = self.sess.struct_span_fatal_with_code( let mut err = self.sess.struct_span_fatal_with_code(
self.span, self.span,
&format!("can't pass `{}` to variadic function", self.ty), &format!("can't pass `{}` to variadic function", self.ty),
@ -45,7 +45,10 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx> {
err err
} }
fn diagnostic_extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> { fn diagnostic_extended(
&self,
mut err: DiagnosticBuilder<'tcx, ErrorReported>,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
err.note(&format!( err.note(&format!(
"certain types, like `{}`, must be casted before passing them to a \ "certain types, like `{}`, must be casted before passing them to a \
variadic function, because of arcane ABI rules dictated by the C \ variadic function, because of arcane ABI rules dictated by the C \

View File

@ -1,5 +1,5 @@
use crate::structured_errors::StructuredDiagnostic; use crate::structured_errors::StructuredDiagnostic;
use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorReported};
use rustc_middle::ty::{Ty, TypeFoldable}; use rustc_middle::ty::{Ty, TypeFoldable};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::Span; use rustc_span::Span;
@ -20,7 +20,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
rustc_errors::error_code!(E0607) rustc_errors::error_code!(E0607)
} }
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> { fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorReported> {
let mut err = self.sess.struct_span_fatal_with_code( let mut err = self.sess.struct_span_fatal_with_code(
self.span, self.span,
&format!( &format!(
@ -37,7 +37,10 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
err err
} }
fn diagnostic_extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> { fn diagnostic_extended(
&self,
mut err: DiagnosticBuilder<'tcx, ErrorReported>,
) -> DiagnosticBuilder<'tcx, ErrorReported> {
err.help( err.help(
"Thin pointers are \"simple\" pointers: they are purely a reference to a "Thin pointers are \"simple\" pointers: they are purely a reference to a
memory address. memory address.

View File

@ -1,5 +1,7 @@
use crate::structured_errors::StructuredDiagnostic; use crate::structured_errors::StructuredDiagnostic;
use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId}; use rustc_errors::{
pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported,
};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_middle::hir::map::fn_sig; use rustc_middle::hir::map::fn_sig;
use rustc_middle::middle::resolve_lifetime::LifetimeScopeForPath; use rustc_middle::middle::resolve_lifetime::LifetimeScopeForPath;
@ -362,7 +364,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
} }
} }
fn start_diagnostics(&self) -> DiagnosticBuilder<'tcx> { fn start_diagnostics(&self) -> DiagnosticBuilder<'tcx, ErrorReported> {
let span = self.path_segment.ident.span; let span = self.path_segment.ident.span;
let msg = self.create_error_message(); let msg = self.create_error_message();
@ -789,7 +791,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
rustc_errors::error_code!(E0107) rustc_errors::error_code!(E0107)
} }
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> { fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorReported> {
let mut err = self.start_diagnostics(); let mut err = self.start_diagnostics();
self.notify(&mut err); self.notify(&mut err);

View File

@ -720,12 +720,10 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
let mut msg = let mut msg =
tcx.sess.struct_err(&format!("couldn't generate documentation: {}", e.error)); tcx.sess.struct_err(&format!("couldn't generate documentation: {}", e.error));
let file = e.file.display().to_string(); let file = e.file.display().to_string();
if file.is_empty() { if !file.is_empty() {
msg.emit() msg.note(&format!("failed to create or modify \"{}\"", file));
} else {
msg.note(&format!("failed to create or modify \"{}\"", file)).emit()
} }
Err(ErrorReported) Err(msg.emit())
} }
} }
} }