Skip to content

Commit 85e67b9

Browse files
committed
Fix ice when error reporting recursion errors
Fixes: #90319, #92148, #93955
1 parent 37b55c8 commit 85e67b9

File tree

9 files changed

+66
-14
lines changed

9 files changed

+66
-14
lines changed

compiler/rustc_middle/src/traits/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ pub enum SelectionError<'tcx> {
478478
/// A given constant couldn't be evaluated.
479479
NotConstEvaluatable(NotConstEvaluatable),
480480
/// Exceeded the recursion depth during type projection.
481-
Overflow,
481+
Overflow(OverflowError),
482482
/// Signaling that an error has already been emitted, to avoid
483483
/// multiple errors being shown.
484484
ErrorReporting,

compiler/rustc_middle/src/traits/select.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use self::EvaluationResult::*;
66

77
use super::{SelectionError, SelectionResult};
8+
use rustc_errors::ErrorGuaranteed;
89

910
use crate::ty;
1011

@@ -264,14 +265,26 @@ impl EvaluationResult {
264265
/// Indicates that trait evaluation caused overflow and in which pass.
265266
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)]
266267
pub enum OverflowError {
268+
Error(ErrorGuaranteed),
267269
Canonical,
268270
ErrorReporting,
269271
}
270272

273+
impl From<ErrorGuaranteed> for OverflowError {
274+
fn from(e: ErrorGuaranteed) -> OverflowError {
275+
OverflowError::Error(e)
276+
}
277+
}
278+
279+
TrivialTypeFoldableAndLiftImpls! {
280+
OverflowError,
281+
}
282+
271283
impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
272284
fn from(overflow_error: OverflowError) -> SelectionError<'tcx> {
273285
match overflow_error {
274-
OverflowError::Canonical => SelectionError::Overflow,
286+
OverflowError::Error(e) => SelectionError::Overflow(OverflowError::Error(e)),
287+
OverflowError::Canonical => SelectionError::Overflow(OverflowError::Canonical),
275288
OverflowError::ErrorReporting => SelectionError::ErrorReporting,
276289
}
277290
}

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc_hir::GenericParam;
2222
use rustc_hir::Item;
2323
use rustc_hir::Node;
2424
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
25+
use rustc_middle::traits::select::OverflowError;
2526
use rustc_middle::ty::error::ExpectedFound;
2627
use rustc_middle::ty::fold::TypeFolder;
2728
use rustc_middle::ty::{
@@ -928,8 +929,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
928929
self.tcx.sess.delay_span_bug(span, "`ErrorGuaranteed` without an error");
929930
return;
930931
}
931-
932-
Overflow => {
932+
// Already reported.
933+
Overflow(OverflowError::Error(_)) => {
934+
self.tcx.sess.delay_span_bug(span, "`OverflowError` has been reported");
935+
return;
936+
}
937+
Overflow(_) => {
933938
bug!("overflow should be handled before the `report_selection_error` path");
934939
}
935940
SelectionError::ErrorReporting => {

compiler/rustc_trait_selection/src/traits/project.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use rustc_hir::def::DefKind;
2727
use rustc_hir::def_id::DefId;
2828
use rustc_hir::lang_items::LangItem;
2929
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
30+
use rustc_middle::traits::select::OverflowError;
3031
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
3132
use rustc_middle::ty::subst::Subst;
3233
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
@@ -1139,7 +1140,9 @@ fn project<'cx, 'tcx>(
11391140
if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) {
11401141
// This should really be an immediate error, but some existing code
11411142
// relies on being able to recover from this.
1142-
return Err(ProjectionError::TraitSelectionError(SelectionError::Overflow));
1143+
return Err(ProjectionError::TraitSelectionError(SelectionError::Overflow(
1144+
OverflowError::Canonical,
1145+
)));
11431146
}
11441147

11451148
if obligation.predicate.references_error() {

compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs

+2
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,11 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
108108
)
109109
}
110110
OverflowError::ErrorReporting => EvaluationResult::EvaluatedToErr,
111+
OverflowError::Error(_) => EvaluationResult::EvaluatedToErr,
111112
})
112113
}
113114
Err(OverflowError::ErrorReporting) => EvaluationResult::EvaluatedToErr,
115+
Err(OverflowError::Error(_)) => EvaluationResult::EvaluatedToErr,
114116
}
115117
}
116118
}

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
164164
Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval }))
165165
}
166166
Ok(_) => Ok(None),
167-
Err(OverflowError::Canonical) => Err(Overflow),
167+
Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)),
168168
Err(OverflowError::ErrorReporting) => Err(ErrorReporting),
169+
Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))),
169170
})
170171
.flat_map(Result::transpose)
171172
.collect::<Result<Vec<_>, _>>()?;

compiler/rustc_trait_selection/src/traits/select/mod.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use crate::traits::project::ProjectionCacheKeyExt;
2929
use crate::traits::ProjectionCacheKey;
3030
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
3131
use rustc_data_structures::stack::ensure_sufficient_stack;
32-
use rustc_errors::Diagnostic;
32+
use rustc_errors::{Diagnostic, ErrorGuaranteed};
3333
use rustc_hir as hir;
3434
use rustc_hir::def_id::DefId;
3535
use rustc_infer::infer::LateBoundRegionConversionTime;
@@ -320,11 +320,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
320320
obligation: &TraitObligation<'tcx>,
321321
) -> SelectionResult<'tcx, Selection<'tcx>> {
322322
let candidate = match self.select_from_obligation(obligation) {
323-
Err(SelectionError::Overflow) => {
323+
Err(SelectionError::Overflow(OverflowError::Canonical)) => {
324324
// In standard mode, overflow must have been caught and reported
325325
// earlier.
326326
assert!(self.query_mode == TraitQueryMode::Canonical);
327-
return Err(SelectionError::Overflow);
327+
return Err(SelectionError::Overflow(OverflowError::Canonical));
328328
}
329329
Err(SelectionError::Ambiguous(_)) => {
330330
return Ok(None);
@@ -339,9 +339,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
339339
};
340340

341341
match self.confirm_candidate(obligation, candidate) {
342-
Err(SelectionError::Overflow) => {
342+
Err(SelectionError::Overflow(OverflowError::Canonical)) => {
343343
assert!(self.query_mode == TraitQueryMode::Canonical);
344-
Err(SelectionError::Overflow)
344+
Err(SelectionError::Overflow(OverflowError::Canonical))
345345
}
346346
Err(e) => Err(e),
347347
Ok(candidate) => {
@@ -958,7 +958,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
958958
Ok(Some(c)) => self.evaluate_candidate(stack, &c),
959959
Err(SelectionError::Ambiguous(_)) => Ok(EvaluatedToAmbig),
960960
Ok(None) => Ok(EvaluatedToAmbig),
961-
Err(Overflow) => Err(OverflowError::Canonical),
961+
Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical),
962962
Err(ErrorReporting) => Err(OverflowError::ErrorReporting),
963963
Err(..) => Ok(EvaluatedToErr),
964964
}
@@ -1117,7 +1117,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11171117
match self.query_mode {
11181118
TraitQueryMode::Standard => {
11191119
if self.infcx.is_tainted_by_errors() {
1120-
return Err(OverflowError::ErrorReporting);
1120+
return Err(OverflowError::Error(
1121+
ErrorGuaranteed::unchecked_claim_error_was_emitted(),
1122+
));
11211123
}
11221124
self.infcx.report_overflow_error(error_obligation, true);
11231125
}
@@ -1353,7 +1355,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13531355
}
13541356

13551357
if self.can_use_global_caches(param_env) {
1356-
if let Err(Overflow) = candidate {
1358+
if let Err(Overflow(OverflowError::Canonical)) = candidate {
13571359
// Don't cache overflow globally; we only produce this in certain modes.
13581360
} else if !pred.needs_infer() {
13591361
if !candidate.needs_infer() {

src/test/ui/typeck/issue-90319.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
struct Wrapper<T>(T);
2+
3+
trait Trait {
4+
fn method(&self) {}
5+
}
6+
7+
impl<'a, T> Trait for Wrapper<&'a T> where Wrapper<T>: Trait {}
8+
9+
fn get<T>() -> T {
10+
unimplemented!()
11+
}
12+
13+
fn main() {
14+
let thing = get::<Thing>();//~ERROR cannot find type `Thing` in this scope [E0412]
15+
let wrapper = Wrapper(thing);
16+
Trait::method(&wrapper);
17+
}

src/test/ui/typeck/issue-90319.stderr

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

0 commit comments

Comments
 (0)