mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Rollup merge of #104554 - BoxyUwU:less_unchecked_pls, r=lcnr
Use `ErrorGuaranteed::unchecked_claim_error_was_emitted` less there are only like 3 or 4 call sites left after this but it wasnt obvious to me how to remove them
This commit is contained in:
commit
7f35493e99
@ -19,7 +19,7 @@ extern crate tracing;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_errors::{Diagnostic, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::bit_set::ChunkedBitSet;
|
||||
@ -192,13 +192,13 @@ fn do_mir_borrowck<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
let mut errors = error::BorrowckErrors::new();
|
||||
let mut errors = error::BorrowckErrors::new(infcx.tcx);
|
||||
|
||||
// Gather the upvars of a closure, if any.
|
||||
let tables = tcx.typeck_opt_const_arg(def);
|
||||
if let Some(ErrorGuaranteed { .. }) = tables.tainted_by_errors {
|
||||
infcx.set_tainted_by_errors();
|
||||
errors.set_tainted_by_errors();
|
||||
if let Some(e) = tables.tainted_by_errors {
|
||||
infcx.set_tainted_by_errors(e);
|
||||
errors.set_tainted_by_errors(e);
|
||||
}
|
||||
let upvars: Vec<_> = tables
|
||||
.closure_min_captures_flattened(def.did)
|
||||
@ -2260,6 +2260,7 @@ mod error {
|
||||
use super::*;
|
||||
|
||||
pub struct BorrowckErrors<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
/// This field keeps track of move errors that are to be reported for given move indices.
|
||||
///
|
||||
/// There are situations where many errors can be reported for a single move out (see #53807)
|
||||
@ -2282,19 +2283,24 @@ mod error {
|
||||
tainted_by_errors: Option<ErrorGuaranteed>,
|
||||
}
|
||||
|
||||
impl BorrowckErrors<'_> {
|
||||
pub fn new() -> Self {
|
||||
impl<'tcx> BorrowckErrors<'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
|
||||
BorrowckErrors {
|
||||
tcx,
|
||||
buffered_move_errors: BTreeMap::new(),
|
||||
buffered: Default::default(),
|
||||
tainted_by_errors: None,
|
||||
}
|
||||
}
|
||||
|
||||
// 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<'_, ErrorGuaranteed>) {
|
||||
self.tainted_by_errors = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
|
||||
if let None = self.tainted_by_errors {
|
||||
self.tainted_by_errors = Some(
|
||||
self.tcx
|
||||
.sess
|
||||
.delay_span_bug(t.span.clone(), "diagnostic buffered but not emitted"),
|
||||
)
|
||||
}
|
||||
t.buffer(&mut self.buffered);
|
||||
}
|
||||
|
||||
@ -2302,8 +2308,8 @@ mod error {
|
||||
t.buffer(&mut self.buffered);
|
||||
}
|
||||
|
||||
pub fn set_tainted_by_errors(&mut self) {
|
||||
self.tainted_by_errors = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
|
||||
pub fn set_tainted_by_errors(&mut self, e: ErrorGuaranteed) {
|
||||
self.tainted_by_errors = Some(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,7 +303,10 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
||||
|
||||
if !nll_errors.is_empty() {
|
||||
// Suppress unhelpful extra errors in `infer_opaque_types`.
|
||||
infcx.set_tainted_by_errors();
|
||||
infcx.set_tainted_by_errors(infcx.tcx.sess.delay_span_bug(
|
||||
body.span,
|
||||
"`compute_regions` tainted `infcx` with errors but did not emit any errors",
|
||||
));
|
||||
}
|
||||
|
||||
let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values);
|
||||
|
@ -219,8 +219,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
||||
instantiated_ty: OpaqueHiddenType<'tcx>,
|
||||
origin: OpaqueTyOrigin,
|
||||
) -> Ty<'tcx> {
|
||||
if self.is_tainted_by_errors() {
|
||||
return self.tcx.ty_error();
|
||||
if let Some(e) = self.tainted_by_errors() {
|
||||
return self.tcx.ty_error_with_guaranteed(e);
|
||||
}
|
||||
|
||||
let definition_ty = instantiated_ty
|
||||
|
@ -115,7 +115,7 @@ pub trait AstConv<'tcx> {
|
||||
/// (e.g., resolve) that is translated into a ty-error. This is
|
||||
/// used to help suppress derived errors typeck might otherwise
|
||||
/// report.
|
||||
fn set_tainted_by_errors(&self);
|
||||
fn set_tainted_by_errors(&self, e: ErrorGuaranteed);
|
||||
|
||||
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
|
||||
}
|
||||
@ -2620,8 +2620,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
}
|
||||
}
|
||||
Res::Err => {
|
||||
self.set_tainted_by_errors();
|
||||
self.tcx().ty_error()
|
||||
let e = self
|
||||
.tcx()
|
||||
.sess
|
||||
.delay_span_bug(path.span, "path with `Res:Err` but no error emitted");
|
||||
self.set_tainted_by_errors(e);
|
||||
self.tcx().ty_error_with_guaranteed(e)
|
||||
}
|
||||
_ => span_bug!(span, "unexpected resolution: {:?}", path.res),
|
||||
}
|
||||
|
@ -518,7 +518,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
||||
ty
|
||||
}
|
||||
|
||||
fn set_tainted_by_errors(&self) {
|
||||
fn set_tainted_by_errors(&self, _: ErrorGuaranteed) {
|
||||
// There's no obvious place to track this, so just let it go.
|
||||
}
|
||||
|
||||
|
@ -1561,7 +1561,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
// Mark that we've failed to coerce the types here to suppress
|
||||
// any superfluous errors we might encounter while trying to
|
||||
// emit or provide suggestions on how to fix the initial error.
|
||||
fcx.set_tainted_by_errors();
|
||||
fcx.set_tainted_by_errors(
|
||||
fcx.tcx.sess.delay_span_bug(cause.span, "coercion error but no error emitted"),
|
||||
);
|
||||
let (expected, found) = if label_expression_as_expected {
|
||||
// In the case where this is a "forced unit", like
|
||||
// `break`, we want to call the `()` "expected"
|
||||
|
@ -154,7 +154,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
Err(e) => e,
|
||||
};
|
||||
|
||||
self.set_tainted_by_errors();
|
||||
self.set_tainted_by_errors(self.tcx.sess.delay_span_bug(
|
||||
expr.span,
|
||||
"`TypeError` when attempting coercion but no error emitted",
|
||||
));
|
||||
let expr = expr.peel_drop_temps();
|
||||
let cause = self.misc(expr.span);
|
||||
let expr_ty = self.resolve_vars_with_obligations(checked_ty);
|
||||
|
@ -527,12 +527,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span);
|
||||
let ty = match res {
|
||||
Res::Err => {
|
||||
self.set_tainted_by_errors();
|
||||
tcx.ty_error()
|
||||
let e =
|
||||
self.tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
|
||||
self.set_tainted_by_errors(e);
|
||||
tcx.ty_error_with_guaranteed(e)
|
||||
}
|
||||
Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) => {
|
||||
report_unexpected_variant_res(tcx, res, qpath, expr.span);
|
||||
tcx.ty_error()
|
||||
let e = report_unexpected_variant_res(tcx, res, qpath, expr.span);
|
||||
tcx.ty_error_with_guaranteed(e)
|
||||
}
|
||||
_ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
|
||||
};
|
||||
@ -1962,7 +1964,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expr_span: Span,
|
||||
) {
|
||||
if variant.is_recovered() {
|
||||
self.set_tainted_by_errors();
|
||||
self.set_tainted_by_errors(
|
||||
self.tcx
|
||||
.sess
|
||||
.delay_span_bug(expr_span, "parser recovered but no error was emitted"),
|
||||
);
|
||||
return;
|
||||
}
|
||||
let mut err = self.err_ctxt().type_error_struct_with_diag(
|
||||
|
@ -104,7 +104,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
// type, `?T` is not considered unsolved, but `?I` is. The
|
||||
// same is true for float variables.)
|
||||
let fallback = match ty.kind() {
|
||||
_ if self.is_tainted_by_errors() => self.tcx.ty_error(),
|
||||
_ if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error_with_guaranteed(e),
|
||||
ty::Infer(ty::IntVar(_)) => self.tcx.types.i32,
|
||||
ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64,
|
||||
_ => match diverging_fallback.get(&ty) {
|
||||
|
@ -140,8 +140,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
debug!("write_ty({:?}, {:?}) in fcx {}", id, self.resolve_vars_if_possible(ty), self.tag());
|
||||
self.typeck_results.borrow_mut().node_types_mut().insert(id, ty);
|
||||
|
||||
if ty.references_error() {
|
||||
self.set_tainted_by_errors();
|
||||
if let Err(e) = ty.error_reported() {
|
||||
self.set_tainted_by_errors(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -528,7 +528,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
|
||||
match self.typeck_results.borrow().node_types().get(id) {
|
||||
Some(&t) => t,
|
||||
None if self.is_tainted_by_errors() => self.tcx.ty_error(),
|
||||
None if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error_with_guaranteed(e),
|
||||
None => {
|
||||
bug!(
|
||||
"no type for node {}: {} in fcx {}",
|
||||
@ -543,7 +543,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn node_ty_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
|
||||
match self.typeck_results.borrow().node_types().get(id) {
|
||||
Some(&t) => Some(t),
|
||||
None if self.is_tainted_by_errors() => Some(self.tcx.ty_error()),
|
||||
None if let Some(e) = self.tainted_by_errors() => Some(self.tcx.ty_error_with_guaranteed(e)),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
@ -1148,9 +1148,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
explicit_late_bound = ExplicitLateBound::Yes;
|
||||
}
|
||||
|
||||
if let Err(GenericArgCountMismatch { reported: Some(_), .. }) = arg_count.correct {
|
||||
if let Err(GenericArgCountMismatch { reported: Some(e), .. }) = arg_count.correct {
|
||||
infer_args_for_err.insert(index);
|
||||
self.set_tainted_by_errors(); // See issue #53251.
|
||||
self.set_tainted_by_errors(e); // See issue #53251.
|
||||
}
|
||||
}
|
||||
|
||||
@ -1440,12 +1440,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if !ty.is_ty_var() {
|
||||
ty
|
||||
} else {
|
||||
if !self.is_tainted_by_errors() {
|
||||
let e = self.tainted_by_errors().unwrap_or_else(|| {
|
||||
self.err_ctxt()
|
||||
.emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282, true)
|
||||
.emit();
|
||||
}
|
||||
let err = self.tcx.ty_error();
|
||||
.emit()
|
||||
});
|
||||
let err = self.tcx.ty_error_with_guaranteed(e);
|
||||
self.demand_suptype(sp, err, ty);
|
||||
err
|
||||
}
|
||||
|
@ -511,8 +511,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
|
||||
}
|
||||
|
||||
self.set_tainted_by_errors();
|
||||
let tcx = self.tcx;
|
||||
// FIXME: taint after emitting errors and pass through an `ErrorGuaranteed`
|
||||
self.set_tainted_by_errors(
|
||||
tcx.sess.delay_span_bug(call_span, "no errors reported for args"),
|
||||
);
|
||||
|
||||
// Get the argument span in the context of the call span so that
|
||||
// suggestions and labels are (more) correct when an arg is a
|
||||
@ -1207,7 +1210,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
|
||||
let variant = match def {
|
||||
Res::Err => {
|
||||
self.set_tainted_by_errors();
|
||||
self.set_tainted_by_errors(
|
||||
self.tcx.sess.delay_span_bug(path_span, "`Res::Err` but no error emitted"),
|
||||
);
|
||||
return None;
|
||||
}
|
||||
Res::Def(DefKind::Variant, _) => match ty.kind() {
|
||||
|
@ -4,6 +4,7 @@ mod checks;
|
||||
mod suggestions;
|
||||
|
||||
pub use _impl::*;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
pub use suggestions::*;
|
||||
|
||||
use crate::coercion::DynamicCoerceMany;
|
||||
@ -289,8 +290,8 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn set_tainted_by_errors(&self) {
|
||||
self.infcx.set_tainted_by_errors()
|
||||
fn set_tainted_by_errors(&self, e: ErrorGuaranteed) {
|
||||
self.infcx.set_tainted_by_errors(e)
|
||||
}
|
||||
|
||||
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, _span: Span) {
|
||||
|
@ -53,7 +53,7 @@ use crate::check::check_fn;
|
||||
use crate::coercion::DynamicCoerceMany;
|
||||
use crate::gather_locals::GatherLocalsVisitor;
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::{struct_span_err, MultiSpan};
|
||||
use rustc_errors::{struct_span_err, ErrorGuaranteed, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
@ -344,7 +344,7 @@ fn typeck_with_fallback<'tcx>(
|
||||
|
||||
fcx.select_all_obligations_or_error();
|
||||
|
||||
if !fcx.infcx.is_tainted_by_errors() {
|
||||
if let None = fcx.infcx.tainted_by_errors() {
|
||||
fcx.check_transmutes();
|
||||
}
|
||||
|
||||
@ -428,7 +428,12 @@ impl<'tcx> EnclosingBreakables<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'_>, span: Span) {
|
||||
fn report_unexpected_variant_res(
|
||||
tcx: TyCtxt<'_>,
|
||||
res: Res,
|
||||
qpath: &hir::QPath<'_>,
|
||||
span: Span,
|
||||
) -> ErrorGuaranteed {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
@ -437,7 +442,7 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'
|
||||
res.descr(),
|
||||
rustc_hir_pretty::qpath_to_string(qpath),
|
||||
)
|
||||
.emit();
|
||||
.emit()
|
||||
}
|
||||
|
||||
/// Controls whether the arguments are tupled. This is used for the call
|
||||
|
@ -133,7 +133,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn is_tainted_by_errors(&self) -> bool {
|
||||
self.infcx.is_tainted_by_errors()
|
||||
self.infcx.tainted_by_errors().is_some()
|
||||
}
|
||||
|
||||
fn resolve_type_vars_or_error(
|
||||
|
@ -839,12 +839,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let (res, opt_ty, segments) = path_resolution;
|
||||
match res {
|
||||
Res::Err => {
|
||||
self.set_tainted_by_errors();
|
||||
return tcx.ty_error();
|
||||
let e = tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
|
||||
self.set_tainted_by_errors(e);
|
||||
return tcx.ty_error_with_guaranteed(e);
|
||||
}
|
||||
Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fictive | CtorKind::Fn), _) => {
|
||||
report_unexpected_variant_res(tcx, res, qpath, pat.span);
|
||||
return tcx.ty_error();
|
||||
let e = report_unexpected_variant_res(tcx, res, qpath, pat.span);
|
||||
return tcx.ty_error_with_guaranteed(e);
|
||||
}
|
||||
Res::SelfCtor(..)
|
||||
| Res::Def(
|
||||
@ -985,9 +986,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let on_error = || {
|
||||
let on_error = |e| {
|
||||
for pat in subpats {
|
||||
self.check_pat(pat, tcx.ty_error(), def_bm, ti);
|
||||
self.check_pat(pat, tcx.ty_error_with_guaranteed(e), def_bm, ti);
|
||||
}
|
||||
};
|
||||
let report_unexpected_res = |res: Res| {
|
||||
@ -1014,36 +1015,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
err.span_label(pat.span, "not a tuple variant or struct");
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
on_error();
|
||||
let e = err.emit();
|
||||
on_error(e);
|
||||
e
|
||||
};
|
||||
|
||||
// Resolve the path and check the definition for errors.
|
||||
let (res, opt_ty, segments) =
|
||||
self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
|
||||
if res == Res::Err {
|
||||
self.set_tainted_by_errors();
|
||||
on_error();
|
||||
return self.tcx.ty_error();
|
||||
let e = tcx.sess.delay_span_bug(pat.span, "`Res:Err` but no error emitted");
|
||||
self.set_tainted_by_errors(e);
|
||||
on_error(e);
|
||||
return tcx.ty_error_with_guaranteed(e);
|
||||
}
|
||||
|
||||
// Type-check the path.
|
||||
let (pat_ty, res) =
|
||||
self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id);
|
||||
if !pat_ty.is_fn() {
|
||||
report_unexpected_res(res);
|
||||
return tcx.ty_error();
|
||||
let e = report_unexpected_res(res);
|
||||
return tcx.ty_error_with_guaranteed(e);
|
||||
}
|
||||
|
||||
let variant = match res {
|
||||
Res::Err => {
|
||||
self.set_tainted_by_errors();
|
||||
on_error();
|
||||
return tcx.ty_error();
|
||||
let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
|
||||
self.set_tainted_by_errors(e);
|
||||
on_error(e);
|
||||
return tcx.ty_error_with_guaranteed(e);
|
||||
}
|
||||
Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => {
|
||||
report_unexpected_res(res);
|
||||
return tcx.ty_error();
|
||||
let e = report_unexpected_res(res);
|
||||
return tcx.ty_error_with_guaranteed(e);
|
||||
}
|
||||
Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res),
|
||||
_ => bug!("unexpected pattern resolution: {:?}", res),
|
||||
@ -1082,9 +1086,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
} else {
|
||||
// Pattern has wrong number of fields.
|
||||
self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err);
|
||||
on_error();
|
||||
return tcx.ty_error();
|
||||
let e = self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err);
|
||||
on_error(e);
|
||||
return tcx.ty_error_with_guaranteed(e);
|
||||
}
|
||||
pat_ty
|
||||
}
|
||||
@ -1098,7 +1102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
fields: &'tcx [ty::FieldDef],
|
||||
expected: Ty<'tcx>,
|
||||
had_err: bool,
|
||||
) {
|
||||
) -> ErrorGuaranteed {
|
||||
let subpats_ending = pluralize!(subpats.len());
|
||||
let fields_ending = pluralize!(fields.len());
|
||||
|
||||
@ -1245,7 +1249,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
err.emit();
|
||||
err.emit()
|
||||
}
|
||||
|
||||
fn check_pat_tuple(
|
||||
|
@ -83,10 +83,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
wbcx.typeck_results.treat_byte_string_as_slice =
|
||||
mem::take(&mut self.typeck_results.borrow_mut().treat_byte_string_as_slice);
|
||||
|
||||
if self.is_tainted_by_errors() {
|
||||
// FIXME(eddyb) keep track of `ErrorGuaranteed` from where the error was emitted.
|
||||
wbcx.typeck_results.tainted_by_errors =
|
||||
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
|
||||
if let Some(e) = self.tainted_by_errors() {
|
||||
wbcx.typeck_results.tainted_by_errors = Some(e);
|
||||
}
|
||||
|
||||
debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results);
|
||||
@ -674,10 +672,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
// We may have introduced e.g. `ty::Error`, if inference failed, make sure
|
||||
// to mark the `TypeckResults` as tainted in that case, so that downstream
|
||||
// users of the typeck results don't produce extra errors, or worse, ICEs.
|
||||
if resolver.replaced_with_error {
|
||||
// FIXME(eddyb) keep track of `ErrorGuaranteed` from where the error was emitted.
|
||||
self.typeck_results.tainted_by_errors =
|
||||
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
|
||||
if let Some(e) = resolver.replaced_with_error {
|
||||
self.typeck_results.tainted_by_errors = Some(e);
|
||||
}
|
||||
|
||||
x
|
||||
@ -708,8 +704,8 @@ struct Resolver<'cx, 'tcx> {
|
||||
span: &'cx dyn Locatable,
|
||||
body: &'tcx hir::Body<'tcx>,
|
||||
|
||||
/// Set to `true` if any `Ty` or `ty::Const` had to be replaced with an `Error`.
|
||||
replaced_with_error: bool,
|
||||
/// Set to `Some` if any `Ty` or `ty::Const` had to be replaced with an `Error`.
|
||||
replaced_with_error: Option<ErrorGuaranteed>,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
|
||||
@ -718,12 +714,14 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
|
||||
span: &'cx dyn Locatable,
|
||||
body: &'tcx hir::Body<'tcx>,
|
||||
) -> Resolver<'cx, 'tcx> {
|
||||
Resolver { tcx: fcx.tcx, infcx: fcx, span, body, replaced_with_error: false }
|
||||
Resolver { tcx: fcx.tcx, infcx: fcx, span, body, replaced_with_error: None }
|
||||
}
|
||||
|
||||
fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) {
|
||||
if !self.tcx.sess.has_errors().is_some() {
|
||||
self.infcx
|
||||
fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
|
||||
match self.tcx.sess.has_errors() {
|
||||
Some(e) => e,
|
||||
None => self
|
||||
.infcx
|
||||
.err_ctxt()
|
||||
.emit_inference_failure_err(
|
||||
Some(self.body.id()),
|
||||
@ -732,7 +730,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
|
||||
E0282,
|
||||
false,
|
||||
)
|
||||
.emit();
|
||||
.emit(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -773,9 +771,9 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
|
||||
}
|
||||
Err(_) => {
|
||||
debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
|
||||
self.report_error(t);
|
||||
self.replaced_with_error = true;
|
||||
self.tcx().ty_error()
|
||||
let e = self.report_error(t);
|
||||
self.replaced_with_error = Some(e);
|
||||
self.tcx().ty_error_with_guaranteed(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -790,9 +788,9 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
|
||||
Ok(ct) => self.tcx.erase_regions(ct),
|
||||
Err(_) => {
|
||||
debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
|
||||
self.report_error(ct);
|
||||
self.replaced_with_error = true;
|
||||
self.tcx().const_error(ct.ty())
|
||||
let e = self.report_error(ct);
|
||||
self.replaced_with_error = Some(e);
|
||||
self.tcx().const_error_with_guaranteed(ct.ty(), e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ pub use rustc_middle::ty::IntVarValue;
|
||||
use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt;
|
||||
@ -1208,7 +1208,8 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
/// reporting errors that often occur as a result of earlier
|
||||
/// errors, but where it's hard to be 100% sure (e.g., unresolved
|
||||
/// inference variables, regionck errors).
|
||||
pub fn is_tainted_by_errors(&self) -> bool {
|
||||
#[must_use = "this method does not have any side effects"]
|
||||
pub fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
|
||||
debug!(
|
||||
"is_tainted_by_errors(err_count={}, err_count_on_creation={}, \
|
||||
tainted_by_errors={})",
|
||||
@ -1217,19 +1218,25 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
self.tainted_by_errors.get().is_some()
|
||||
);
|
||||
|
||||
if self.tcx.sess.err_count() > self.err_count_on_creation {
|
||||
return true; // errors reported since this infcx was made
|
||||
if let Some(e) = self.tainted_by_errors.get() {
|
||||
return Some(e);
|
||||
}
|
||||
self.tainted_by_errors.get().is_some()
|
||||
|
||||
if self.tcx.sess.err_count() > self.err_count_on_creation {
|
||||
// errors reported since this infcx was made
|
||||
let e = self.tcx.sess.has_errors().unwrap();
|
||||
self.set_tainted_by_errors(e);
|
||||
return Some(e);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Set the "tainted by errors" flag to true. We call this when we
|
||||
/// observe an error from a prior pass.
|
||||
pub fn set_tainted_by_errors(&self) {
|
||||
debug!("set_tainted_by_errors()");
|
||||
self.tainted_by_errors.set(Some(
|
||||
self.tcx.sess.delay_span_bug(DUMMY_SP, "`InferCtxt` incorrectly tainted by errors"),
|
||||
));
|
||||
pub fn set_tainted_by_errors(&self, e: ErrorGuaranteed) {
|
||||
debug!("set_tainted_by_errors(ErrorGuaranteed)");
|
||||
self.tainted_by_errors.set(Some(e));
|
||||
}
|
||||
|
||||
pub fn skip_region_resolution(&self) {
|
||||
@ -1270,7 +1277,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let inner = &mut *inner;
|
||||
assert!(
|
||||
self.is_tainted_by_errors() || inner.region_obligations.is_empty(),
|
||||
self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
|
||||
"region_obligations not empty: {:#?}",
|
||||
inner.region_obligations
|
||||
);
|
||||
@ -1707,7 +1714,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
) {
|
||||
let errors = self.resolve_regions(outlives_env);
|
||||
|
||||
if !self.is_tainted_by_errors() {
|
||||
if let None = self.tainted_by_errors() {
|
||||
// As a heuristic, just skip reporting region errors
|
||||
// altogether if other errors have been reported while
|
||||
// this infcx was in use. This is totally hokey but
|
||||
|
@ -116,9 +116,9 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
(&ty::Error(_), _) | (_, &ty::Error(_)) => {
|
||||
infcx.set_tainted_by_errors();
|
||||
Ok(self.tcx().ty_error())
|
||||
(&ty::Error(e), _) | (_, &ty::Error(e)) => {
|
||||
infcx.set_tainted_by_errors(e);
|
||||
Ok(self.tcx().ty_error_with_guaranteed(e))
|
||||
}
|
||||
|
||||
(&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
|
||||
|
@ -562,7 +562,10 @@ impl Session {
|
||||
if self.err_count() == old_count {
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
|
||||
Err(self.delay_span_bug(
|
||||
rustc_span::DUMMY_SP,
|
||||
"`self.err_count()` changed but an error was not emitted",
|
||||
))
|
||||
}
|
||||
}
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
|
@ -532,9 +532,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
root_obligation: &PredicateObligation<'tcx>,
|
||||
error: &SelectionError<'tcx>,
|
||||
) {
|
||||
self.set_tainted_by_errors();
|
||||
let tcx = self.tcx;
|
||||
let mut span = obligation.cause.span;
|
||||
// FIXME: statically guarantee this by tainting after the diagnostic is emitted
|
||||
self.set_tainted_by_errors(
|
||||
tcx.sess.delay_span_bug(span, "`report_selection_error` did not emit an error"),
|
||||
);
|
||||
|
||||
let mut err = match *error {
|
||||
SelectionError::Unimplemented => {
|
||||
@ -2060,7 +2063,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
// check upstream for type errors and don't add the obligations to
|
||||
// begin with in those cases.
|
||||
if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
|
||||
if !self.is_tainted_by_errors() {
|
||||
if let None = self.tainted_by_errors() {
|
||||
self.emit_inference_failure_err(
|
||||
body_id,
|
||||
span,
|
||||
@ -2115,16 +2118,16 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
if impls.len() > 1 && impls.len() < 5 && has_non_region_infer {
|
||||
self.annotate_source_of_ambiguity(&mut err, &impls, predicate);
|
||||
} else {
|
||||
if self.is_tainted_by_errors() {
|
||||
err.delay_as_bug();
|
||||
if self.tainted_by_errors().is_some() {
|
||||
err.cancel();
|
||||
return;
|
||||
}
|
||||
err.note(&format!("cannot satisfy `{}`", predicate));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if self.is_tainted_by_errors() {
|
||||
err.delay_as_bug();
|
||||
if self.tainted_by_errors().is_some() {
|
||||
err.cancel();
|
||||
return;
|
||||
}
|
||||
err.note(&format!("cannot satisfy `{}`", predicate));
|
||||
@ -2226,7 +2229,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
] = path.segments
|
||||
&& data.trait_ref.def_id == *trait_id
|
||||
&& self.tcx.trait_of_item(*item_id) == Some(*trait_id)
|
||||
&& !self.is_tainted_by_errors()
|
||||
&& let None = self.tainted_by_errors()
|
||||
{
|
||||
let (verb, noun) = match self.tcx.associated_item(item_id).kind {
|
||||
ty::AssocKind::Const => ("refer to the", "constant"),
|
||||
@ -2295,7 +2298,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
// with error messages.
|
||||
if arg.references_error()
|
||||
|| self.tcx.sess.has_errors().is_some()
|
||||
|| self.is_tainted_by_errors()
|
||||
|| self.tainted_by_errors().is_some()
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -2306,7 +2309,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
ty::PredicateKind::Subtype(data) => {
|
||||
if data.references_error()
|
||||
|| self.tcx.sess.has_errors().is_some()
|
||||
|| self.is_tainted_by_errors()
|
||||
|| self.tainted_by_errors().is_some()
|
||||
{
|
||||
// no need to overload user in such cases
|
||||
return;
|
||||
@ -2317,7 +2320,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282, true)
|
||||
}
|
||||
ty::PredicateKind::Projection(data) => {
|
||||
if predicate.references_error() || self.is_tainted_by_errors() {
|
||||
if predicate.references_error() || self.tainted_by_errors().is_some() {
|
||||
return;
|
||||
}
|
||||
let subst = data
|
||||
@ -2351,7 +2354,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
|
||||
ty::PredicateKind::ConstEvaluatable(data) => {
|
||||
if predicate.references_error() || self.is_tainted_by_errors() {
|
||||
if predicate.references_error() || self.tainted_by_errors().is_some() {
|
||||
return;
|
||||
}
|
||||
let subst = data.walk().find(|g| g.is_non_region_infer());
|
||||
@ -2378,7 +2381,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if self.tcx.sess.has_errors().is_some() || self.is_tainted_by_errors() {
|
||||
if self.tcx.sess.has_errors().is_some() || self.tainted_by_errors().is_some() {
|
||||
return;
|
||||
}
|
||||
let mut err = struct_span_err!(
|
||||
@ -2422,7 +2425,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
post.sort();
|
||||
post.dedup();
|
||||
|
||||
if self.is_tainted_by_errors()
|
||||
if self.tainted_by_errors().is_some()
|
||||
&& (crate_names.len() == 1
|
||||
&& spans.len() == 0
|
||||
&& ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())
|
||||
|
@ -33,7 +33,7 @@ use crate::traits::ProjectionCacheKey;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
||||
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;
|
||||
@ -1089,10 +1089,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
if !self.infcx.tcx.recursion_limit().value_within_limit(depth) {
|
||||
match self.query_mode {
|
||||
TraitQueryMode::Standard => {
|
||||
if self.infcx.is_tainted_by_errors() {
|
||||
return Err(OverflowError::Error(
|
||||
ErrorGuaranteed::unchecked_claim_error_was_emitted(),
|
||||
));
|
||||
if let Some(e) = self.infcx.tainted_by_errors() {
|
||||
return Err(OverflowError::Error(e));
|
||||
}
|
||||
self.infcx.err_ctxt().report_overflow_error(error_obligation, true);
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
// compile-flags:-Ztreat-err-as-bug=5
|
||||
#[derive(Debug)]
|
||||
enum MyError {
|
||||
NotFound { key: Vec<u8> },
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0507]: cannot move out of `*key` which is behind a shared reference
|
||||
--> $DIR/issue-52262.rs:16:35
|
||||
--> $DIR/issue-52262.rs:15:35
|
||||
|
|
||||
LL | String::from_utf8(*key).unwrap()
|
||||
| ^^^^ move occurs because `*key` has type `Vec<u8>`, which does not implement the `Copy` trait
|
||||
|
Loading…
Reference in New Issue
Block a user