1
Fork 0

rustc_error: make ErrorReported impossible to construct

There are a few places were we have to construct it, though, and a few
places that are more invasive to change. To do this, we create a
constructor with a long obvious name.
This commit is contained in:
mark 2022-01-22 18:49:12 -06:00
parent 461e807801
commit bb8d4307eb
104 changed files with 705 additions and 550 deletions

View file

@ -51,7 +51,7 @@ pub fn codegen_fulfill_obligation<'tcx>(
// leading to an ambiguous result. So report this as an
// overflow bug, since I believe this is the only case
// where ambiguity can result.
infcx.tcx.sess.delay_span_bug(
let reported = infcx.tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP,
&format!(
"encountered ambiguity selecting `{:?}` during codegen, presuming due to \
@ -59,21 +59,21 @@ pub fn codegen_fulfill_obligation<'tcx>(
trait_ref
),
);
return Err(ErrorGuaranteed);
return Err(reported);
}
Err(Unimplemented) => {
// This can trigger when we probe for the source of a `'static` lifetime requirement
// on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound.
// This can also trigger when we have a global bound that is not actually satisfied,
// but was included during typeck due to the trivial_bounds feature.
infcx.tcx.sess.delay_span_bug(
let guar = infcx.tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP,
&format!(
"Encountered error `Unimplemented` selecting `{:?}` during codegen",
trait_ref
),
);
return Err(ErrorGuaranteed);
return Err(guar);
}
Err(e) => {
bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)

View file

@ -18,7 +18,7 @@ use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::thir;
use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable};
use rustc_middle::ty::subst::{Subst, SubstsRef};
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, DelaySpanBugEmitted, TyCtxt, TypeFoldable};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
@ -177,8 +177,9 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
false => NotConstEvaluatable::MentionsParam,
}),
Err(ErrorHandled::Linted) => {
infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
Err(NotConstEvaluatable::Error(ErrorGuaranteed))
let reported =
infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
Err(NotConstEvaluatable::Error(reported))
}
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
Ok(_) => Ok(()),
@ -244,7 +245,7 @@ impl<'tcx> AbstractConst<'tcx> {
) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
match ct.val() {
ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()),
ty::ConstKind::Error(_) => Err(ErrorGuaranteed),
ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => Err(reported),
_ => Ok(None),
}
}
@ -280,17 +281,19 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
}
fn error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> {
self.tcx
let reported = self
.tcx
.sess
.struct_span_err(self.root_span(), "overly complex generic constant")
.span_label(span, msg)
.help("consider moving this anonymous constant into a `const` function")
.emit();
Err(ErrorGuaranteed)
Err(reported)
}
fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> {
self.tcx
let reported = self
.tcx
.sess
.struct_span_err(self.root_span(), "overly complex generic constant")
.span_label(span, msg)
@ -298,7 +301,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
.note("this operation may be supported in the future")
.emit();
Err(ErrorGuaranteed)
Err(reported)
}
fn new(
@ -553,11 +556,7 @@ pub(super) fn thir_abstract_const<'tcx>(
_ => return Ok(None),
}
let body = tcx.thir_body(def);
if body.0.borrow().exprs.is_empty() {
// type error in constant, there is no thir
return Err(ErrorGuaranteed);
}
let body = tcx.thir_body(def)?;
AbstractConstBuilder::new(tcx, (&*body.0.borrow(), body.1))?
.map(AbstractConstBuilder::build)
@ -580,7 +579,7 @@ pub(super) fn try_unify_abstract_consts<'tcx>(
Ok(false)
})()
.unwrap_or_else(|ErrorGuaranteed| true)
.unwrap_or_else(|_: ErrorGuaranteed| true)
// FIXME(generic_const_exprs): We should instead have this
// method return the resulting `ty::Const` and return `ConstKind::Error`
// on `ErrorGuaranteed`.

View file

@ -63,7 +63,7 @@ pub trait InferCtxtExt<'tcx> {
errors: &[FulfillmentError<'tcx>],
body_id: Option<hir::BodyId>,
fallback_has_occurred: bool,
);
) -> ErrorGuaranteed;
fn report_overflow_error<T>(
&self,
@ -111,7 +111,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
errors: &[FulfillmentError<'tcx>],
body_id: Option<hir::BodyId>,
fallback_has_occurred: bool,
) {
) -> ErrorGuaranteed {
#[derive(Debug)]
struct ErrorDescriptor<'tcx> {
predicate: ty::Predicate<'tcx>,
@ -190,6 +190,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
self.report_fulfillment_error(error, body_id, fallback_has_occurred);
}
}
self.tcx.sess.delay_span_bug(DUMMY_SP, "expected fullfillment errors")
}
/// Reports that an overflow has occurred and halts compilation. We
@ -312,7 +314,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let predicate_is_const = ty::BoundConstness::ConstIfConst
== trait_predicate.skip_binder().constness;
if self.tcx.sess.has_errors() && trait_predicate.references_error() {
if self.tcx.sess.has_errors().is_some()
&& trait_predicate.references_error()
{
return;
}
let trait_ref = trait_predicate.to_poly_trait_ref();
@ -919,7 +923,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
// Already reported in the query.
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(ErrorGuaranteed)) => {
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) => {
// FIXME(eddyb) remove this once `ErrorGuaranteed` becomes a proof token.
self.tcx.sess.delay_span_bug(span, "`ErrorGuaranteed` without an error");
return;
@ -1857,7 +1861,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
// Same hacky approach as above to avoid deluging user
// with error messages.
if arg.references_error()
|| self.tcx.sess.has_errors()
|| self.tcx.sess.has_errors().is_some()
|| self.is_tainted_by_errors()
{
return;
@ -1868,7 +1872,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
ty::PredicateKind::Subtype(data) => {
if data.references_error()
|| self.tcx.sess.has_errors()
|| self.tcx.sess.has_errors().is_some()
|| self.is_tainted_by_errors()
{
// no need to overload user in such cases
@ -1910,7 +1914,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
}
_ => {
if self.tcx.sess.has_errors() || self.is_tainted_by_errors() {
if self.tcx.sess.has_errors().is_some() || self.is_tainted_by_errors() {
return;
}
let mut err = struct_span_err!(

View file

@ -3,7 +3,6 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::obligation_forest::ProcessResult;
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
use rustc_errors::ErrorGuaranteed;
use rustc_infer::traits::ProjectionCacheKey;
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
use rustc_middle::mir::interpret::ErrorHandled;
@ -630,14 +629,12 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
),
}
}
(Err(ErrorHandled::Reported(ErrorGuaranteed)), _)
| (_, Err(ErrorHandled::Reported(ErrorGuaranteed))) => {
ProcessResult::Error(CodeSelectionError(
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(
ErrorGuaranteed,
)),
))
}
(Err(ErrorHandled::Reported(reported)), _)
| (_, Err(ErrorHandled::Reported(reported))) => ProcessResult::Error(
CodeSelectionError(SelectionError::NotConstEvaluatable(
NotConstEvaluatable::Error(reported),
)),
),
(Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => {
span_bug!(
obligation.cause.span(self.selcx.tcx()),

View file

@ -231,8 +231,8 @@ fn do_normalize_predicates<'tcx>(
match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, predicates) {
Ok(predicates) => predicates,
Err(errors) => {
infcx.report_fulfillment_errors(&errors, None, false);
return Err(ErrorGuaranteed);
let reported = infcx.report_fulfillment_errors(&errors, None, false);
return Err(reported);
}
};
@ -258,13 +258,15 @@ fn do_normalize_predicates<'tcx>(
// represents a legitimate failure due to some kind of
// unconstrained variable, and it seems better not to ICE,
// all things considered.
tcx.sess.span_err(span, &fixup_err.to_string());
return Err(ErrorGuaranteed);
let reported = tcx.sess.span_err(span, &fixup_err.to_string());
return Err(reported);
}
};
if predicates.needs_infer() {
tcx.sess.delay_span_bug(span, "encountered inference variables after `fully_resolve`");
Err(ErrorGuaranteed)
let reported = tcx
.sess
.delay_span_bug(span, "encountered inference variables after `fully_resolve`");
Err(reported)
} else {
Ok(predicates)
}

View file

@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
use rustc_parse_format::{ParseMode, Parser, Piece, Position};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
use rustc_span::{Span, DUMMY_SP};
#[derive(Clone, Debug)]
pub struct OnUnimplementedFormatString(Symbol);
@ -47,8 +47,7 @@ fn parse_error(
if let Some(note) = note {
diag.note(note);
}
diag.emit();
ErrorGuaranteed
diag.emit()
}
impl<'tcx> OnUnimplementedDirective {
@ -59,7 +58,7 @@ impl<'tcx> OnUnimplementedDirective {
span: Span,
is_root: bool,
) -> Result<Self, ErrorGuaranteed> {
let mut errored = false;
let mut errored = None;
let mut item_iter = items.iter();
let parse_value = |value_str| {
@ -91,8 +90,8 @@ impl<'tcx> OnUnimplementedDirective {
)
})?;
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
if let Some(symbol) = item.value_str() && parse_value(symbol).is_err() {
errored = true;
if let Some(symbol) = item.value_str() && let Err(guar) = parse_value(symbol) {
errored = Some(guar);
}
true
});
@ -134,13 +133,10 @@ impl<'tcx> OnUnimplementedDirective {
&& note.is_none()
{
if let Some(items) = item.meta_item_list() {
if let Ok(subcommand) =
Self::parse(tcx, item_def_id, &items, item.span(), false)
{
subcommands.push(subcommand);
} else {
errored = true;
}
match Self::parse(tcx, item_def_id, &items, item.span(), false) {
Ok(subcommand) => subcommands.push(subcommand),
Err(reported) => errored = Some(reported),
};
continue;
}
} else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() {
@ -163,8 +159,8 @@ impl<'tcx> OnUnimplementedDirective {
);
}
if errored {
Err(ErrorGuaranteed)
if let Some(reported) = errored {
Err(reported)
} else {
Ok(OnUnimplementedDirective {
condition,
@ -203,7 +199,9 @@ impl<'tcx> OnUnimplementedDirective {
append_const_msg: None,
}))
} else {
return Err(ErrorGuaranteed);
let reported =
tcx.sess.delay_span_bug(DUMMY_SP, "of_item: neither meta_item_list nor value_str");
return Err(reported);
};
debug!("of_item({:?}) = {:?}", item_def_id, result);
result
@ -327,7 +325,7 @@ impl<'tcx> OnUnimplementedFormatString {
match generics.params.iter().find(|param| param.name == s) {
Some(_) => (),
None => {
struct_span_err!(
let reported = struct_span_err!(
tcx.sess,
span,
E0230,
@ -340,20 +338,20 @@ impl<'tcx> OnUnimplementedFormatString {
}
)
.emit();
result = Err(ErrorGuaranteed);
result = Err(reported);
}
}
}
// `{:1}` and `{}` are not to be used
Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
struct_span_err!(
let reported = struct_span_err!(
tcx.sess,
span,
E0231,
"only named substitution parameters are allowed"
)
.emit();
result = Err(ErrorGuaranteed);
result = Err(reported);
}
},
}

View file

@ -1396,7 +1396,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// `rustc_ty_utils::instance::resolve_associated_item()`.
let node_item =
assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
.map_err(|ErrorGuaranteed| ())?;
.map_err(|ErrorGuaranteed { .. }| ())?;
if node_item.is_final() {
// Non-specializable items are always projectable.

View file

@ -29,7 +29,7 @@ use crate::traits::project::ProjectionCacheKeyExt;
use crate::traits::ProjectionCacheKey;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{Diagnostic, ErrorGuaranteed};
use rustc_errors::Diagnostic;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::LateBoundRegionConversionTime;
@ -674,8 +674,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Err(_) => Ok(EvaluatedToErr),
}
}
(Err(ErrorHandled::Reported(ErrorGuaranteed)), _)
| (_, Err(ErrorHandled::Reported(ErrorGuaranteed))) => Ok(EvaluatedToErr),
(Err(ErrorHandled::Reported(_)), _)
| (_, Err(ErrorHandled::Reported(_))) => Ok(EvaluatedToErr),
(Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => {
span_bug!(
obligation.cause.span(self.tcx()),

View file

@ -16,14 +16,14 @@ use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use crate::traits::select::IntercrateAmbiguityCause;
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_errors::{struct_span_err, EmissionGuarantee};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::lint::LintDiagnosticBuilder;
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
use rustc_span::DUMMY_SP;
use rustc_span::{Span, DUMMY_SP};
use super::util::impl_trait_ref_and_oblig;
use super::{FulfillmentContext, SelectionContext};
@ -377,8 +377,7 @@ fn report_negative_positive_conflict(
}
}
sg.has_errored = true;
err.emit();
sg.has_errored = Some(err.emit());
}
fn report_conflicting_impls(
@ -394,7 +393,13 @@ fn report_conflicting_impls(
// Work to be done after we've built the DiagnosticBuilder. We have to define it
// now because the struct_lint methods don't return back the DiagnosticBuilder
// that's passed in.
let decorate = |err: LintDiagnosticBuilder<'_>| {
fn decorate<G: EmissionGuarantee>(
tcx: TyCtxt<'_>,
overlap: OverlapError,
used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
impl_span: Span,
err: LintDiagnosticBuilder<'_, G>,
) -> G {
let msg = format!(
"conflicting implementations of trait `{}`{}{}",
overlap.trait_desc,
@ -440,17 +445,25 @@ fn report_conflicting_impls(
coherence::add_placeholder_note(&mut err);
}
err.emit()
};
}
match used_to_be_allowed {
None => {
sg.has_errored = true;
if overlap.with_impl.is_local() || !tcx.orphan_check_crate(()).contains(&impl_def_id) {
let reported = if overlap.with_impl.is_local()
|| !tcx.orphan_check_crate(()).contains(&impl_def_id)
{
let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
decorate(LintDiagnosticBuilder::new(err.forget_guarantee()));
Some(decorate(
tcx,
overlap,
used_to_be_allowed,
impl_span,
LintDiagnosticBuilder::new(err),
))
} else {
tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check");
}
Some(tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check"))
};
sg.has_errored = reported;
}
Some(kind) => {
let lint = match kind {
@ -461,8 +474,10 @@ fn report_conflicting_impls(
lint,
tcx.hir().local_def_id_to_hir_id(impl_def_id),
impl_span,
decorate,
)
|ldb| {
decorate(tcx, overlap, used_to_be_allowed, impl_span, ldb);
},
);
}
};
}