Skip to content

Commit 05a6daa

Browse files
Report overflows gracefully with new solver
1 parent 2a198c7 commit 05a6daa

File tree

14 files changed

+75
-27
lines changed

14 files changed

+75
-27
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
578578

579579
#[instrument(skip(self), level = "debug")]
580580
pub(in super::super) fn report_ambiguity_errors(&self) {
581-
let mut errors = self.fulfillment_cx.borrow_mut().collect_remaining_errors();
581+
let mut errors = self.fulfillment_cx.borrow_mut().collect_remaining_errors(self);
582582

583583
if !errors.is_empty() {
584584
self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);

compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7878
// Finally, for ambiguity-related errors, we actually want to look
7979
// for a parameter that is the source of the inference type left
8080
// over in this predicate.
81-
if let traits::FulfillmentErrorCode::CodeAmbiguity = error.code {
81+
if let traits::FulfillmentErrorCode::CodeAmbiguity { .. } = error.code {
8282
fallback_param_to_point_at = None;
8383
self_param_to_point_at = None;
8484
param_to_point_at =

compiler/rustc_infer/src/traits/engine.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
3838

3939
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
4040

41-
fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>>;
41+
fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
4242

4343
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
4444

@@ -78,6 +78,6 @@ impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
7878
return errors;
7979
}
8080

81-
self.collect_remaining_errors()
81+
self.collect_remaining_errors(infcx)
8282
}
8383
}

compiler/rustc_infer/src/traits/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,11 @@ pub enum FulfillmentErrorCode<'tcx> {
128128
CodeProjectionError(MismatchedProjectionTypes<'tcx>),
129129
CodeSubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
130130
CodeConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
131-
CodeAmbiguity,
131+
CodeAmbiguity {
132+
/// Overflow reported from the new solver `-Ztrait-solver=next`, which will
133+
/// be reported as an regular error as opposed to a fatal error.
134+
overflow: bool,
135+
},
132136
}
133137

134138
impl<'tcx, O> Obligation<'tcx, O> {

compiler/rustc_infer/src/traits/structural_impls.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
4646
super::CodeConstEquateError(ref a, ref b) => {
4747
write!(f, "CodeConstEquateError({:?}, {:?})", a, b)
4848
}
49-
super::CodeAmbiguity => write!(f, "Ambiguity"),
49+
super::CodeAmbiguity { overflow: false } => write!(f, "Ambiguity"),
50+
super::CodeAmbiguity { overflow: true } => write!(f, "Overflow"),
5051
super::CodeCycle(ref cycle) => write!(f, "Cycle({:?})", cycle),
5152
}
5253
}

compiler/rustc_trait_selection/src/solve/fulfill.rs

+24-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::mem;
22

33
use rustc_infer::infer::InferCtxt;
4+
use rustc_infer::traits::solve::MaybeCause;
45
use rustc_infer::traits::Obligation;
56
use rustc_infer::traits::{
67
query::NoSolution, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes,
@@ -41,13 +42,31 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
4142
self.obligations.push(obligation);
4243
}
4344

44-
fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
45+
fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
4546
self.obligations
4647
.drain(..)
47-
.map(|obligation| FulfillmentError {
48-
obligation: obligation.clone(),
49-
code: FulfillmentErrorCode::CodeAmbiguity,
50-
root_obligation: obligation,
48+
.map(|obligation| {
49+
let code =
50+
infcx.probe(|_| match infcx.evaluate_root_goal(obligation.clone().into()) {
51+
Ok((_, Certainty::Maybe(MaybeCause::Ambiguity), _)) => {
52+
FulfillmentErrorCode::CodeAmbiguity { overflow: false }
53+
}
54+
Ok((_, Certainty::Maybe(MaybeCause::Overflow), _)) => {
55+
FulfillmentErrorCode::CodeAmbiguity { overflow: true }
56+
}
57+
Ok((_, Certainty::Yes, _)) => {
58+
bug!("did not expect successful goal when collecting ambiguity errors")
59+
}
60+
Err(_) => {
61+
bug!("did not expect selection error when collecting ambiguity errors")
62+
}
63+
});
64+
65+
FulfillmentError {
66+
obligation: obligation.clone(),
67+
code,
68+
root_obligation: obligation,
69+
}
5170
})
5271
.collect()
5372
}

compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,16 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
4040
self.obligations.insert(obligation);
4141
}
4242

43-
fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
43+
fn collect_remaining_errors(
44+
&mut self,
45+
_infcx: &InferCtxt<'tcx>,
46+
) -> Vec<FulfillmentError<'tcx>> {
4447
// any remaining obligations are errors
4548
self.obligations
4649
.iter()
4750
.map(|obligation| FulfillmentError {
4851
obligation: obligation.clone(),
49-
code: FulfillmentErrorCode::CodeAmbiguity,
52+
code: FulfillmentErrorCode::CodeAmbiguity { overflow: false },
5053
// FIXME - does Chalk have a notation of 'root obligation'?
5154
// This is just for diagnostics, so it's okay if this is wrong
5255
root_obligation: obligation.clone(),

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

+14-1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ pub trait TypeErrCtxtExt<'tcx> {
125125
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
126126
<T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
127127

128+
fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed;
129+
128130
fn report_fulfillment_errors(&self, errors: &[FulfillmentError<'tcx>]) -> ErrorGuaranteed;
129131

130132
fn report_overflow_obligation<T>(
@@ -602,6 +604,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
602604
);
603605
}
604606

607+
fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed {
608+
let obligation = self.resolve_vars_if_possible(obligation);
609+
let mut err = self.build_overflow_error(&obligation.predicate, obligation.cause.span, true);
610+
self.note_obligation_cause(&mut err, &obligation);
611+
self.point_at_returns_when_relevant(&mut err, &obligation);
612+
err.emit()
613+
}
614+
605615
fn report_selection_error(
606616
&self,
607617
mut obligation: PredicateObligation<'tcx>,
@@ -1658,9 +1668,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
16581668
FulfillmentErrorCode::CodeProjectionError(ref e) => {
16591669
self.report_projection_error(&error.obligation, e);
16601670
}
1661-
FulfillmentErrorCode::CodeAmbiguity => {
1671+
FulfillmentErrorCode::CodeAmbiguity { overflow: false } => {
16621672
self.maybe_report_ambiguity(&error.obligation);
16631673
}
1674+
FulfillmentErrorCode::CodeAmbiguity { overflow: true } => {
1675+
self.report_overflow_no_abort(error.obligation.clone());
1676+
}
16641677
FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
16651678
self.report_mismatched_types(
16661679
&error.obligation.cause,

compiler/rustc_trait_selection/src/traits/fulfill.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,15 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
133133
.register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
134134
}
135135

136-
fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
137-
self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
136+
fn collect_remaining_errors(
137+
&mut self,
138+
_infcx: &InferCtxt<'tcx>,
139+
) -> Vec<FulfillmentError<'tcx>> {
140+
self.predicates
141+
.to_errors(CodeAmbiguity { overflow: false })
142+
.into_iter()
143+
.map(to_fulfillment_error)
144+
.collect()
138145
}
139146

140147
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {

tests/ui/higher-rank-trait-bounds/issue-95230.new.stderr

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
error[E0282]: type annotations needed
1+
error[E0275]: overflow evaluating the requirement `for<'a> &'a mut Bar well-formed`
22
--> $DIR/issue-95230.rs:9:13
33
|
44
LL | for<'a> &'a mut Self:;
5-
| ^^^^^^^^^^^^ cannot infer type for mutable reference `&'a mut Bar`
5+
| ^^^^^^^^^^^^
66
|
7+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_95230`)
78
note: required by a bound in `Bar`
89
--> $DIR/issue-95230.rs:9:13
910
|
@@ -15,4 +16,4 @@ LL | for<'a> &'a mut Self:;
1516

1617
error: aborting due to previous error
1718

18-
For more information about this error, try `rustc --explain E0282`.
19+
For more information about this error, try `rustc --explain E0275`.

tests/ui/traits/new-solver/recursive-self-normalization-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fn needs_bar<S: Bar>() {}
1313

1414
fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
1515
needs_bar::<T::Assoc1>();
16-
//~^ ERROR type annotations needed
16+
//~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
1717
}
1818

1919
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0283]: type annotations needed: cannot satisfy `<T as Foo1>::Assoc1: Bar`
1+
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
22
--> $DIR/recursive-self-normalization-2.rs:15:5
33
|
44
LL | needs_bar::<T::Assoc1>();
55
| ^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: cannot satisfy `<T as Foo1>::Assoc1: Bar`
7+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
88
note: required by a bound in `needs_bar`
99
--> $DIR/recursive-self-normalization-2.rs:12:17
1010
|
@@ -13,4 +13,4 @@ LL | fn needs_bar<S: Bar>() {}
1313

1414
error: aborting due to previous error
1515

16-
For more information about this error, try `rustc --explain E0283`.
16+
For more information about this error, try `rustc --explain E0275`.

tests/ui/traits/new-solver/recursive-self-normalization.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ fn needs_bar<S: Bar>() {}
99

1010
fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
1111
needs_bar::<T::Assoc>();
12-
//~^ ERROR type annotations needed
12+
//~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
1313
}
1414

1515
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0283]: type annotations needed: cannot satisfy `<T as Foo>::Assoc: Bar`
1+
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
22
--> $DIR/recursive-self-normalization.rs:11:5
33
|
44
LL | needs_bar::<T::Assoc>();
55
| ^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: cannot satisfy `<T as Foo>::Assoc: Bar`
7+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
88
note: required by a bound in `needs_bar`
99
--> $DIR/recursive-self-normalization.rs:8:17
1010
|
@@ -13,4 +13,4 @@ LL | fn needs_bar<S: Bar>() {}
1313

1414
error: aborting due to previous error
1515

16-
For more information about this error, try `rustc --explain E0283`.
16+
For more information about this error, try `rustc --explain E0275`.

0 commit comments

Comments
 (0)