Rollup merge of #94391 - light4:issue-90319, r=estebank

Fix ice when error reporting recursion errors

Fixes: #90319, #92148, #93955
This commit is contained in:
Dylan DPC 2022-03-25 01:34:28 +01:00 committed by GitHub
commit d1d4613ead
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 66 additions and 14 deletions

View file

@ -491,7 +491,7 @@ pub enum SelectionError<'tcx> {
/// A given constant couldn't be evaluated. /// A given constant couldn't be evaluated.
NotConstEvaluatable(NotConstEvaluatable), NotConstEvaluatable(NotConstEvaluatable),
/// Exceeded the recursion depth during type projection. /// Exceeded the recursion depth during type projection.
Overflow, Overflow(OverflowError),
/// Signaling that an error has already been emitted, to avoid /// Signaling that an error has already been emitted, to avoid
/// multiple errors being shown. /// multiple errors being shown.
ErrorReporting, ErrorReporting,

View file

@ -5,6 +5,7 @@
use self::EvaluationResult::*; use self::EvaluationResult::*;
use super::{SelectionError, SelectionResult}; use super::{SelectionError, SelectionResult};
use rustc_errors::ErrorGuaranteed;
use crate::ty; use crate::ty;
@ -264,14 +265,26 @@ impl EvaluationResult {
/// Indicates that trait evaluation caused overflow and in which pass. /// Indicates that trait evaluation caused overflow and in which pass.
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)] #[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)]
pub enum OverflowError { pub enum OverflowError {
Error(ErrorGuaranteed),
Canonical, Canonical,
ErrorReporting, ErrorReporting,
} }
impl From<ErrorGuaranteed> for OverflowError {
fn from(e: ErrorGuaranteed) -> OverflowError {
OverflowError::Error(e)
}
}
TrivialTypeFoldableAndLiftImpls! {
OverflowError,
}
impl<'tcx> From<OverflowError> for SelectionError<'tcx> { impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
fn from(overflow_error: OverflowError) -> SelectionError<'tcx> { fn from(overflow_error: OverflowError) -> SelectionError<'tcx> {
match overflow_error { match overflow_error {
OverflowError::Canonical => SelectionError::Overflow, OverflowError::Error(e) => SelectionError::Overflow(OverflowError::Error(e)),
OverflowError::Canonical => SelectionError::Overflow(OverflowError::Canonical),
OverflowError::ErrorReporting => SelectionError::ErrorReporting, OverflowError::ErrorReporting => SelectionError::ErrorReporting,
} }
} }

View file

@ -22,6 +22,7 @@ use rustc_hir::GenericParam;
use rustc_hir::Item; use rustc_hir::Item;
use rustc_hir::Node; use rustc_hir::Node;
use rustc_middle::thir::abstract_const::NotConstEvaluatable; use rustc_middle::thir::abstract_const::NotConstEvaluatable;
use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::fold::TypeFolder;
use rustc_middle::ty::{ use rustc_middle::ty::{
@ -928,8 +929,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
self.tcx.sess.delay_span_bug(span, "`ErrorGuaranteed` without an error"); self.tcx.sess.delay_span_bug(span, "`ErrorGuaranteed` without an error");
return; return;
} }
// Already reported.
Overflow => { Overflow(OverflowError::Error(_)) => {
self.tcx.sess.delay_span_bug(span, "`OverflowError` has been reported");
return;
}
Overflow(_) => {
bug!("overflow should be handled before the `report_selection_error` path"); bug!("overflow should be handled before the `report_selection_error` path");
} }
SelectionError::ErrorReporting => { SelectionError::ErrorReporting => {

View file

@ -27,6 +27,7 @@ use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_infer::infer::resolve::OpportunisticRegionResolver;
use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
use rustc_middle::ty::subst::Subst; use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt}; use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
@ -1139,7 +1140,9 @@ fn project<'cx, 'tcx>(
if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) { if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) {
// This should really be an immediate error, but some existing code // This should really be an immediate error, but some existing code
// relies on being able to recover from this. // relies on being able to recover from this.
return Err(ProjectionError::TraitSelectionError(SelectionError::Overflow)); return Err(ProjectionError::TraitSelectionError(SelectionError::Overflow(
OverflowError::Canonical,
)));
} }
if obligation.predicate.references_error() { if obligation.predicate.references_error() {

View file

@ -108,9 +108,11 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
) )
} }
OverflowError::ErrorReporting => EvaluationResult::EvaluatedToErr, OverflowError::ErrorReporting => EvaluationResult::EvaluatedToErr,
OverflowError::Error(_) => EvaluationResult::EvaluatedToErr,
}) })
} }
Err(OverflowError::ErrorReporting) => EvaluationResult::EvaluatedToErr, Err(OverflowError::ErrorReporting) => EvaluationResult::EvaluatedToErr,
Err(OverflowError::Error(_)) => EvaluationResult::EvaluatedToErr,
} }
} }
} }

View file

@ -164,8 +164,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval })) Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval }))
} }
Ok(_) => Ok(None), Ok(_) => Ok(None),
Err(OverflowError::Canonical) => Err(Overflow), Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)),
Err(OverflowError::ErrorReporting) => Err(ErrorReporting), Err(OverflowError::ErrorReporting) => Err(ErrorReporting),
Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))),
}) })
.flat_map(Result::transpose) .flat_map(Result::transpose)
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;

View file

@ -25,7 +25,7 @@ use crate::traits::project::ProjectionCacheKeyExt;
use crate::traits::ProjectionCacheKey; use crate::traits::ProjectionCacheKey;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::Diagnostic; use rustc_errors::{Diagnostic, ErrorGuaranteed};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::LateBoundRegionConversionTime;
@ -316,11 +316,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &TraitObligation<'tcx>, obligation: &TraitObligation<'tcx>,
) -> SelectionResult<'tcx, Selection<'tcx>> { ) -> SelectionResult<'tcx, Selection<'tcx>> {
let candidate = match self.select_from_obligation(obligation) { let candidate = match self.select_from_obligation(obligation) {
Err(SelectionError::Overflow) => { Err(SelectionError::Overflow(OverflowError::Canonical)) => {
// In standard mode, overflow must have been caught and reported // In standard mode, overflow must have been caught and reported
// earlier. // earlier.
assert!(self.query_mode == TraitQueryMode::Canonical); assert!(self.query_mode == TraitQueryMode::Canonical);
return Err(SelectionError::Overflow); return Err(SelectionError::Overflow(OverflowError::Canonical));
} }
Err(SelectionError::Ambiguous(_)) => { Err(SelectionError::Ambiguous(_)) => {
return Ok(None); return Ok(None);
@ -335,9 +335,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}; };
match self.confirm_candidate(obligation, candidate) { match self.confirm_candidate(obligation, candidate) {
Err(SelectionError::Overflow) => { Err(SelectionError::Overflow(OverflowError::Canonical)) => {
assert!(self.query_mode == TraitQueryMode::Canonical); assert!(self.query_mode == TraitQueryMode::Canonical);
Err(SelectionError::Overflow) Err(SelectionError::Overflow(OverflowError::Canonical))
} }
Err(e) => Err(e), Err(e) => Err(e),
Ok(candidate) => { Ok(candidate) => {
@ -954,7 +954,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(Some(c)) => self.evaluate_candidate(stack, &c), Ok(Some(c)) => self.evaluate_candidate(stack, &c),
Err(SelectionError::Ambiguous(_)) => Ok(EvaluatedToAmbig), Err(SelectionError::Ambiguous(_)) => Ok(EvaluatedToAmbig),
Ok(None) => Ok(EvaluatedToAmbig), Ok(None) => Ok(EvaluatedToAmbig),
Err(Overflow) => Err(OverflowError::Canonical), Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical),
Err(ErrorReporting) => Err(OverflowError::ErrorReporting), Err(ErrorReporting) => Err(OverflowError::ErrorReporting),
Err(..) => Ok(EvaluatedToErr), Err(..) => Ok(EvaluatedToErr),
} }
@ -1113,7 +1113,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
match self.query_mode { match self.query_mode {
TraitQueryMode::Standard => { TraitQueryMode::Standard => {
if self.infcx.is_tainted_by_errors() { if self.infcx.is_tainted_by_errors() {
return Err(OverflowError::ErrorReporting); return Err(OverflowError::Error(
ErrorGuaranteed::unchecked_claim_error_was_emitted(),
));
} }
self.infcx.report_overflow_error(error_obligation, true); self.infcx.report_overflow_error(error_obligation, true);
} }
@ -1349,7 +1351,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} }
if self.can_use_global_caches(param_env) { if self.can_use_global_caches(param_env) {
if let Err(Overflow) = candidate { if let Err(Overflow(OverflowError::Canonical)) = candidate {
// Don't cache overflow globally; we only produce this in certain modes. // Don't cache overflow globally; we only produce this in certain modes.
} else if !pred.needs_infer() { } else if !pred.needs_infer() {
if !candidate.needs_infer() { if !candidate.needs_infer() {

View file

@ -0,0 +1,17 @@
struct Wrapper<T>(T);
trait Trait {
fn method(&self) {}
}
impl<'a, T> Trait for Wrapper<&'a T> where Wrapper<T>: Trait {}
fn get<T>() -> T {
unimplemented!()
}
fn main() {
let thing = get::<Thing>();//~ERROR cannot find type `Thing` in this scope [E0412]
let wrapper = Wrapper(thing);
Trait::method(&wrapper);
}

View file

@ -0,0 +1,9 @@
error[E0412]: cannot find type `Thing` in this scope
--> $DIR/issue-90319.rs:14:23
|
LL | let thing = get::<Thing>();
| ^^^^^ not found in this scope
error: aborting due to previous error
For more information about this error, try `rustc --explain E0412`.