From c1ec8ff14d491642d8c8ae5a9f3c94db4eda9f26 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 17 Nov 2022 20:45:11 +0000 Subject: [PATCH 1/7] dont unchecked create `ErrorGuaranteed` in `BorrowckErrors` --- compiler/rustc_borrowck/src/lib.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 4a4887f1970..c9daed3ab00 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -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 { + if let Some(e) = tables.tainted_by_errors { infcx.set_tainted_by_errors(); - errors.set_tainted_by_errors(); + 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,20 @@ mod error { tainted_by_errors: Option, } - 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()); + 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 +2304,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); } } From 9c510048fdd9b78bda5084d56fffb69da677d967 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 17 Nov 2022 20:57:45 +0000 Subject: [PATCH 2/7] `InferCtxt::is_tainted_by_errors` returns `ErrorGuaranteed` --- compiler/rustc_borrowck/src/lib.rs | 2 +- .../src/region_infer/opaque_types.rs | 4 ++-- compiler/rustc_hir_typeck/src/fallback.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 6 ++--- compiler/rustc_hir_typeck/src/lib.rs | 2 +- .../src/mem_categorization.rs | 2 +- compiler/rustc_hir_typeck/src/writeback.rs | 6 ++--- compiler/rustc_infer/src/infer/mod.rs | 14 +++++++----- .../src/traits/error_reporting/mod.rs | 22 +++++++++---------- .../src/traits/select/mod.rs | 8 +++---- 10 files changed, 33 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index c9daed3ab00..1591048d657 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -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; diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index b2db77944fd..b1060d9505c 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -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.is_tainted_by_errors() { + return self.tcx.ty_error_with_guaranteed(e); } let definition_ty = instantiated_ty diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 5d44092a5f6..653c841290d 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -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.is_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) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index c826a886ca6..86e7f818d54 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -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.is_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> { 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.is_tainted_by_errors() => Some(self.tcx.ty_error_with_guaranteed(e)), None => None, } } @@ -1440,7 +1440,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !ty.is_ty_var() { ty } else { - if !self.is_tainted_by_errors() { + if let None = self.is_tainted_by_errors() { self.err_ctxt() .emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282, true) .emit(); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 6fd609aeaa0..56d8ce2a5c6 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -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.is_tainted_by_errors() { fcx.check_transmutes(); } diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 362f1c34300..495502da406 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -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.is_tainted_by_errors().is_some() } fn resolve_type_vars_or_error( diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 2eca40d678a..d3b704a672b 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -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.is_tainted_by_errors() { + wbcx.typeck_results.tainted_by_errors = Some(e); } debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index fd3b3e4d59f..f966c7bb776 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1208,7 +1208,7 @@ 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 { + pub fn is_tainted_by_errors(&self) -> Option { debug!( "is_tainted_by_errors(err_count={}, err_count_on_creation={}, \ tainted_by_errors={})", @@ -1218,9 +1218,13 @@ impl<'tcx> InferCtxt<'tcx> { ); if self.tcx.sess.err_count() > self.err_count_on_creation { - return true; // errors reported since this infcx was made + // errors reported since this infcx was made + return Some(self.tcx.sess.delay_span_bug( + DUMMY_SP, + "`tcx.sess.error_count()` incorrectly returned non zero value", + )); } - self.tainted_by_errors.get().is_some() + self.tainted_by_errors.get() } /// Set the "tainted by errors" flag to true. We call this when we @@ -1270,7 +1274,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.is_tainted_by_errors().is_some() || inner.region_obligations.is_empty(), "region_obligations not empty: {:#?}", inner.region_obligations ); @@ -1707,7 +1711,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ) { let errors = self.resolve_regions(outlives_env); - if !self.is_tainted_by_errors() { + if let None = self.is_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 diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index f087afa20ba..c96c1f78146 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2060,7 +2060,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.is_tainted_by_errors() { self.emit_inference_failure_err( body_id, span, @@ -2115,16 +2115,14 @@ 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.is_tainted_by_errors().is_some() { return; } err.note(&format!("cannot satisfy `{}`", predicate)); } } _ => { - if self.is_tainted_by_errors() { - err.delay_as_bug(); + if self.is_tainted_by_errors().is_some() { return; } err.note(&format!("cannot satisfy `{}`", predicate)); @@ -2226,7 +2224,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.is_tainted_by_errors() { let (verb, noun) = match self.tcx.associated_item(item_id).kind { ty::AssocKind::Const => ("refer to the", "constant"), @@ -2295,7 +2293,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.is_tainted_by_errors().is_some() { return; } @@ -2306,7 +2304,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.is_tainted_by_errors().is_some() { // no need to overload user in such cases return; @@ -2317,7 +2315,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.is_tainted_by_errors().is_some() { return; } let subst = data @@ -2351,7 +2349,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.is_tainted_by_errors().is_some() { return; } let subst = data.walk().find(|g| g.is_non_region_infer()); @@ -2378,7 +2376,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.is_tainted_by_errors().is_some() { return; } let mut err = struct_span_err!( @@ -2422,7 +2420,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { post.sort(); post.dedup(); - if self.is_tainted_by_errors() + if self.is_tainted_by_errors().is_some() && (crate_names.len() == 1 && spans.len() == 0 && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str()) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index c369c5de52b..8a2bfb5351f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -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.is_tainted_by_errors() { + return Err(OverflowError::Error(e)); } self.infcx.err_ctxt().report_overflow_error(error_obligation, true); } From 95a267bb345dcb13b52a66e322d730414996e439 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 17 Nov 2022 21:03:06 +0000 Subject: [PATCH 3/7] make `replaced_with_error` store `ErrorGuaranteed` --- compiler/rustc_hir_typeck/src/writeback.rs | 33 +++++++++++----------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index d3b704a672b..a620a05aca2 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -672,10 +672,9 @@ 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 { + if let Some(e) = 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()); + self.typeck_results.tainted_by_errors = Some(e); } x @@ -706,8 +705,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, } impl<'cx, 'tcx> Resolver<'cx, 'tcx> { @@ -716,12 +715,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>) { - if !self.tcx.sess.has_errors().is_some() { - self.infcx + fn report_error(&self, p: impl Into>) -> ErrorGuaranteed { + match self.tcx.sess.has_errors() { + Some(e) => e, + None => self + .infcx .err_ctxt() .emit_inference_failure_err( Some(self.body.id()), @@ -730,7 +731,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { E0282, false, ) - .emit(); + .emit(), } } } @@ -771,9 +772,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) } } } @@ -788,9 +789,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) } } } From 3fca95a5976aa89612869203f7ffe857d689b033 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 17 Nov 2022 21:09:59 +0000 Subject: [PATCH 4/7] `track_errors` use a delay_span_bug --- compiler/rustc_session/src/session.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 10352198357..d602acec53e 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -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)] From 1c48039a873f331a4591a499f71161b5c8997af1 Mon Sep 17 00:00:00 2001 From: Boxy Date: Fri, 18 Nov 2022 10:25:32 +0000 Subject: [PATCH 5/7] rename `is_tainted_by_errors` --- compiler/rustc_borrowck/src/lib.rs | 10 ++++++--- .../src/region_infer/opaque_types.rs | 2 +- compiler/rustc_hir_typeck/src/fallback.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 6 ++--- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 1 + compiler/rustc_hir_typeck/src/lib.rs | 2 +- .../src/mem_categorization.rs | 2 +- compiler/rustc_hir_typeck/src/writeback.rs | 3 +-- compiler/rustc_infer/src/infer/mod.rs | 20 ++++++++++------- .../src/traits/error_reporting/mod.rs | 22 ++++++++++--------- .../src/traits/select/mod.rs | 2 +- src/test/ui/issues/issue-52262.rs | 1 - src/test/ui/issues/issue-52262.stderr | 2 +- 13 files changed, 42 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 1591048d657..e8b97966314 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2294,9 +2294,13 @@ mod error { } pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) { - self.tainted_by_errors = Some( - self.tcx.sess.delay_span_bug(t.span.clone(), "diagnostic buffered but not 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); } diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index b1060d9505c..b9885952a89 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -219,7 +219,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { instantiated_ty: OpaqueHiddenType<'tcx>, origin: OpaqueTyOrigin, ) -> Ty<'tcx> { - if let Some(e) = self.is_tainted_by_errors() { + if let Some(e) = self.tainted_by_errors() { return self.tcx.ty_error_with_guaranteed(e); } diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 653c841290d..ac6b0924ab5 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -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 let Some(e) = self.is_tainted_by_errors() => self.tcx.ty_error_with_guaranteed(e), + _ 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) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 86e7f818d54..0d9189b12f6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -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 let Some(e) = self.is_tainted_by_errors() => self.tcx.ty_error_with_guaranteed(e), + 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> { match self.typeck_results.borrow().node_types().get(id) { Some(&t) => Some(t), - None if let Some(e) = self.is_tainted_by_errors() => Some(self.tcx.ty_error_with_guaranteed(e)), + None if let Some(e) = self.tainted_by_errors() => Some(self.tcx.ty_error_with_guaranteed(e)), None => None, } } @@ -1440,7 +1440,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !ty.is_ty_var() { ty } else { - if let None = self.is_tainted_by_errors() { + if let None = self.tainted_by_errors() { self.err_ctxt() .emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282, true) .emit(); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index c3833b4872d..6847b03f431 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -73,6 +73,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.typeck_results.borrow().expr_ty_adjusted(expr); let ty = self.resolve_vars_if_possible(ty); if ty.has_non_region_infer() { + assert!(self.tainted_by_errors().is_some()); self.tcx.ty_error() } else { self.tcx.erase_regions(ty) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 56d8ce2a5c6..51cc2e7882d 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -344,7 +344,7 @@ fn typeck_with_fallback<'tcx>( fcx.select_all_obligations_or_error(); - if let None = fcx.infcx.is_tainted_by_errors() { + if let None = fcx.infcx.tainted_by_errors() { fcx.check_transmutes(); } diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 495502da406..0b5dc946c1d 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -133,7 +133,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } fn is_tainted_by_errors(&self) -> bool { - self.infcx.is_tainted_by_errors().is_some() + self.infcx.tainted_by_errors().is_some() } fn resolve_type_vars_or_error( diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index a620a05aca2..6c2ee35fa50 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -83,7 +83,7 @@ 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 let Some(e) = self.is_tainted_by_errors() { + if let Some(e) = self.tainted_by_errors() { wbcx.typeck_results.tainted_by_errors = Some(e); } @@ -673,7 +673,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // 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 let Some(e) = resolver.replaced_with_error { - // FIXME(eddyb) keep track of `ErrorGuaranteed` from where the error was emitted. self.typeck_results.tainted_by_errors = Some(e); } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f966c7bb776..aa6fed13611 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -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) -> Option { + #[must_use = "this method does not have any side effects"] + pub fn tainted_by_errors(&self) -> Option { debug!( "is_tainted_by_errors(err_count={}, err_count_on_creation={}, \ tainted_by_errors={})", @@ -1217,14 +1218,17 @@ impl<'tcx> InferCtxt<'tcx> { self.tainted_by_errors.get().is_some() ); + if let Some(e) = self.tainted_by_errors.get() { + return Some(e); + } + if self.tcx.sess.err_count() > self.err_count_on_creation { // errors reported since this infcx was made - return Some(self.tcx.sess.delay_span_bug( - DUMMY_SP, - "`tcx.sess.error_count()` incorrectly returned non zero value", - )); + self.set_tainted_by_errors(); + return self.tainted_by_errors.get(); } - self.tainted_by_errors.get() + + None } /// Set the "tainted by errors" flag to true. We call this when we @@ -1274,7 +1278,7 @@ impl<'tcx> InferCtxt<'tcx> { let mut inner = self.inner.borrow_mut(); let inner = &mut *inner; assert!( - self.is_tainted_by_errors().is_some() || inner.region_obligations.is_empty(), + self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(), "region_obligations not empty: {:#?}", inner.region_obligations ); @@ -1711,7 +1715,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ) { let errors = self.resolve_regions(outlives_env); - if let None = 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 diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index c96c1f78146..b84a1c447ff 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2060,7 +2060,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 let None = self.is_tainted_by_errors() { + if let None = self.tainted_by_errors() { self.emit_inference_failure_err( body_id, span, @@ -2115,14 +2115,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().is_some() { + if self.tainted_by_errors().is_some() { + err.cancel(); return; } err.note(&format!("cannot satisfy `{}`", predicate)); } } _ => { - if self.is_tainted_by_errors().is_some() { + if self.tainted_by_errors().is_some() { + err.cancel(); return; } err.note(&format!("cannot satisfy `{}`", predicate)); @@ -2224,7 +2226,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) - && let None = 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"), @@ -2293,7 +2295,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().is_some() + || self.tainted_by_errors().is_some() { return; } @@ -2304,7 +2306,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().is_some() + || self.tainted_by_errors().is_some() { // no need to overload user in such cases return; @@ -2315,7 +2317,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().is_some() { + if predicate.references_error() || self.tainted_by_errors().is_some() { return; } let subst = data @@ -2349,7 +2351,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ty::PredicateKind::ConstEvaluatable(data) => { - if predicate.references_error() || self.is_tainted_by_errors().is_some() { + if predicate.references_error() || self.tainted_by_errors().is_some() { return; } let subst = data.walk().find(|g| g.is_non_region_infer()); @@ -2376,7 +2378,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } _ => { - if self.tcx.sess.has_errors().is_some() || self.is_tainted_by_errors().is_some() { + if self.tcx.sess.has_errors().is_some() || self.tainted_by_errors().is_some() { return; } let mut err = struct_span_err!( @@ -2420,7 +2422,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { post.sort(); post.dedup(); - if self.is_tainted_by_errors().is_some() + if self.tainted_by_errors().is_some() && (crate_names.len() == 1 && spans.len() == 0 && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str()) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 8a2bfb5351f..b05942353a3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1089,7 +1089,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if !self.infcx.tcx.recursion_limit().value_within_limit(depth) { match self.query_mode { TraitQueryMode::Standard => { - if let Some(e) = self.infcx.is_tainted_by_errors() { + if let Some(e) = self.infcx.tainted_by_errors() { return Err(OverflowError::Error(e)); } self.infcx.err_ctxt().report_overflow_error(error_obligation, true); diff --git a/src/test/ui/issues/issue-52262.rs b/src/test/ui/issues/issue-52262.rs index 2195b895557..547643f0d6e 100644 --- a/src/test/ui/issues/issue-52262.rs +++ b/src/test/ui/issues/issue-52262.rs @@ -1,4 +1,3 @@ -// compile-flags:-Ztreat-err-as-bug=5 #[derive(Debug)] enum MyError { NotFound { key: Vec }, diff --git a/src/test/ui/issues/issue-52262.stderr b/src/test/ui/issues/issue-52262.stderr index c0bde4b2321..ef41f078b80 100644 --- a/src/test/ui/issues/issue-52262.stderr +++ b/src/test/ui/issues/issue-52262.stderr @@ -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`, which does not implement the `Copy` trait From 9ed348376fcdc49beb20cbd64760d2a923b76312 Mon Sep 17 00:00:00 2001 From: Boxy Date: Fri, 18 Nov 2022 11:30:21 +0000 Subject: [PATCH 6/7] require an `ErrorGuaranteed` to taint infcx with errors --- compiler/rustc_borrowck/src/lib.rs | 2 +- compiler/rustc_borrowck/src/nll.rs | 5 +- .../rustc_hir_analysis/src/astconv/mod.rs | 10 ++-- compiler/rustc_hir_analysis/src/collect.rs | 2 +- compiler/rustc_hir_typeck/src/coercion.rs | 4 +- compiler/rustc_hir_typeck/src/demand.rs | 5 +- compiler/rustc_hir_typeck/src/expr.rs | 16 ++++-- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 8 +-- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 9 +++- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 5 +- compiler/rustc_hir_typeck/src/lib.rs | 11 ++-- compiler/rustc_hir_typeck/src/pat.rs | 50 ++++++++++--------- compiler/rustc_infer/src/infer/mod.rs | 15 +++--- compiler/rustc_infer/src/infer/sub.rs | 6 +-- .../src/traits/error_reporting/mod.rs | 5 +- 15 files changed, 94 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index e8b97966314..163170a1d1a 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -197,7 +197,7 @@ fn do_mir_borrowck<'tcx>( // Gather the upvars of a closure, if any. let tables = tcx.typeck_opt_const_arg(def); if let Some(e) = tables.tainted_by_errors { - infcx.set_tainted_by_errors(); + infcx.set_tainted_by_errors(e); errors.set_tainted_by_errors(e); } let upvars: Vec<_> = tables diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index f8856b56d14..4a12e1b1b92 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -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); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 16c40cf1299..83b95fe0e91 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -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), } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 2f64a88f03a..a738ee4a148 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -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. } diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 174b4331382..fc05cbf276e 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1544,7 +1544,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" diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 9ca7730daa6..5a34ab40174 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -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); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 13a03b33de8..752d2e0ff78 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -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( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 0d9189b12f6..c2a5c5b6c1b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -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); } } @@ -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. } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 6847b03f431..91063b43d61 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -512,8 +512,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 @@ -1208,7 +1211,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() { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index d5e4b6de581..177d521d280 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -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) { diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 51cc2e7882d..334d6d0aa6c 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -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; @@ -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 diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index eb10f3e2c10..a62d4356130 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -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( diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index aa6fed13611..b9ed6b28c22 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -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; @@ -1224,8 +1224,9 @@ impl<'tcx> InferCtxt<'tcx> { if self.tcx.sess.err_count() > self.err_count_on_creation { // errors reported since this infcx was made - self.set_tainted_by_errors(); - return self.tainted_by_errors.get(); + let e = self.tcx.sess.has_errors().unwrap(); + self.set_tainted_by_errors(e); + return Some(e); } None @@ -1233,11 +1234,9 @@ impl<'tcx> InferCtxt<'tcx> { /// 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) { diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 8c8445a4d9e..bd3c5780b89 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -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 => { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index b84a1c447ff..ad0785d3817 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -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 => { From 45a09a4683f551d96f7e5b16a125c26003beffaf Mon Sep 17 00:00:00 2001 From: Boxy Date: Fri, 18 Nov 2022 13:45:42 +0000 Subject: [PATCH 7/7] review comments 2 electric boogalo --- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 8 ++++---- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index c2a5c5b6c1b..b85a2325728 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1440,12 +1440,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !ty.is_ty_var() { ty } else { - if let None = self.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 } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 91063b43d61..a31ab9c8b23 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -73,7 +73,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.typeck_results.borrow().expr_ty_adjusted(expr); let ty = self.resolve_vars_if_possible(ty); if ty.has_non_region_infer() { - assert!(self.tainted_by_errors().is_some()); self.tcx.ty_error() } else { self.tcx.erase_regions(ty)