mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Rollup merge of #110103 - compiler-errors:new-solver-overflows, r=lcnr
Report overflows gracefully with new solver avoid reporting overflows as ambiguity errors, so that the error message is clearer. r? ```@lcnr```
This commit is contained in:
commit
92eb36461b
@ -578,7 +578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub(in super::super) fn report_ambiguity_errors(&self) {
|
||||
let mut errors = self.fulfillment_cx.borrow_mut().collect_remaining_errors();
|
||||
let mut errors = self.fulfillment_cx.borrow_mut().collect_remaining_errors(self);
|
||||
|
||||
if !errors.is_empty() {
|
||||
self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
|
||||
|
@ -78,7 +78,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// Finally, for ambiguity-related errors, we actually want to look
|
||||
// for a parameter that is the source of the inference type left
|
||||
// over in this predicate.
|
||||
if let traits::FulfillmentErrorCode::CodeAmbiguity = error.code {
|
||||
if let traits::FulfillmentErrorCode::CodeAmbiguity { .. } = error.code {
|
||||
fallback_param_to_point_at = None;
|
||||
self_param_to_point_at = None;
|
||||
param_to_point_at =
|
||||
|
@ -38,7 +38,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
|
||||
|
||||
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
|
||||
|
||||
fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>>;
|
||||
fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
|
||||
|
||||
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
|
||||
|
||||
@ -78,6 +78,6 @@ impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
|
||||
return errors;
|
||||
}
|
||||
|
||||
self.collect_remaining_errors()
|
||||
self.collect_remaining_errors(infcx)
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,11 @@ pub enum FulfillmentErrorCode<'tcx> {
|
||||
CodeProjectionError(MismatchedProjectionTypes<'tcx>),
|
||||
CodeSubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
|
||||
CodeConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
|
||||
CodeAmbiguity,
|
||||
CodeAmbiguity {
|
||||
/// Overflow reported from the new solver `-Ztrait-solver=next`, which will
|
||||
/// be reported as an regular error as opposed to a fatal error.
|
||||
overflow: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'tcx, O> Obligation<'tcx, O> {
|
||||
|
@ -46,7 +46,8 @@ impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
|
||||
super::CodeConstEquateError(ref a, ref b) => {
|
||||
write!(f, "CodeConstEquateError({:?}, {:?})", a, b)
|
||||
}
|
||||
super::CodeAmbiguity => write!(f, "Ambiguity"),
|
||||
super::CodeAmbiguity { overflow: false } => write!(f, "Ambiguity"),
|
||||
super::CodeAmbiguity { overflow: true } => write!(f, "Overflow"),
|
||||
super::CodeCycle(ref cycle) => write!(f, "Cycle({:?})", cycle),
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::mem;
|
||||
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::traits::solve::MaybeCause;
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_infer::traits::{
|
||||
query::NoSolution, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes,
|
||||
@ -41,13 +42,31 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
|
||||
self.obligations.push(obligation);
|
||||
}
|
||||
|
||||
fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
|
||||
fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
|
||||
self.obligations
|
||||
.drain(..)
|
||||
.map(|obligation| FulfillmentError {
|
||||
obligation: obligation.clone(),
|
||||
code: FulfillmentErrorCode::CodeAmbiguity,
|
||||
root_obligation: obligation,
|
||||
.map(|obligation| {
|
||||
let code =
|
||||
infcx.probe(|_| match infcx.evaluate_root_goal(obligation.clone().into()) {
|
||||
Ok((_, Certainty::Maybe(MaybeCause::Ambiguity), _)) => {
|
||||
FulfillmentErrorCode::CodeAmbiguity { overflow: false }
|
||||
}
|
||||
Ok((_, Certainty::Maybe(MaybeCause::Overflow), _)) => {
|
||||
FulfillmentErrorCode::CodeAmbiguity { overflow: true }
|
||||
}
|
||||
Ok((_, Certainty::Yes, _)) => {
|
||||
bug!("did not expect successful goal when collecting ambiguity errors")
|
||||
}
|
||||
Err(_) => {
|
||||
bug!("did not expect selection error when collecting ambiguity errors")
|
||||
}
|
||||
});
|
||||
|
||||
FulfillmentError {
|
||||
obligation: obligation.clone(),
|
||||
code,
|
||||
root_obligation: obligation,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -40,13 +40,16 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
||||
self.obligations.insert(obligation);
|
||||
}
|
||||
|
||||
fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
|
||||
fn collect_remaining_errors(
|
||||
&mut self,
|
||||
_infcx: &InferCtxt<'tcx>,
|
||||
) -> Vec<FulfillmentError<'tcx>> {
|
||||
// any remaining obligations are errors
|
||||
self.obligations
|
||||
.iter()
|
||||
.map(|obligation| FulfillmentError {
|
||||
obligation: obligation.clone(),
|
||||
code: FulfillmentErrorCode::CodeAmbiguity,
|
||||
code: FulfillmentErrorCode::CodeAmbiguity { overflow: false },
|
||||
// FIXME - does Chalk have a notation of 'root obligation'?
|
||||
// This is just for diagnostics, so it's okay if this is wrong
|
||||
root_obligation: obligation.clone(),
|
||||
|
@ -125,6 +125,8 @@ pub trait TypeErrCtxtExt<'tcx> {
|
||||
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
|
||||
<T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
|
||||
|
||||
fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed;
|
||||
|
||||
fn report_fulfillment_errors(&self, errors: &[FulfillmentError<'tcx>]) -> ErrorGuaranteed;
|
||||
|
||||
fn report_overflow_obligation<T>(
|
||||
@ -602,6 +604,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed {
|
||||
let obligation = self.resolve_vars_if_possible(obligation);
|
||||
let mut err = self.build_overflow_error(&obligation.predicate, obligation.cause.span, true);
|
||||
self.note_obligation_cause(&mut err, &obligation);
|
||||
self.point_at_returns_when_relevant(&mut err, &obligation);
|
||||
err.emit()
|
||||
}
|
||||
|
||||
fn report_selection_error(
|
||||
&self,
|
||||
mut obligation: PredicateObligation<'tcx>,
|
||||
@ -1658,9 +1668,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
FulfillmentErrorCode::CodeProjectionError(ref e) => {
|
||||
self.report_projection_error(&error.obligation, e);
|
||||
}
|
||||
FulfillmentErrorCode::CodeAmbiguity => {
|
||||
FulfillmentErrorCode::CodeAmbiguity { overflow: false } => {
|
||||
self.maybe_report_ambiguity(&error.obligation);
|
||||
}
|
||||
FulfillmentErrorCode::CodeAmbiguity { overflow: true } => {
|
||||
self.report_overflow_no_abort(error.obligation.clone());
|
||||
}
|
||||
FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
|
||||
self.report_mismatched_types(
|
||||
&error.obligation.cause,
|
||||
|
@ -133,8 +133,15 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
||||
.register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
|
||||
}
|
||||
|
||||
fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
|
||||
self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
|
||||
fn collect_remaining_errors(
|
||||
&mut self,
|
||||
_infcx: &InferCtxt<'tcx>,
|
||||
) -> Vec<FulfillmentError<'tcx>> {
|
||||
self.predicates
|
||||
.to_errors(CodeAmbiguity { overflow: false })
|
||||
.into_iter()
|
||||
.map(to_fulfillment_error)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
|
||||
|
@ -1,9 +1,10 @@
|
||||
error[E0282]: type annotations needed
|
||||
error[E0275]: overflow evaluating the requirement `for<'a> &'a mut Bar well-formed`
|
||||
--> $DIR/issue-95230.rs:9:13
|
||||
|
|
||||
LL | for<'a> &'a mut Self:;
|
||||
| ^^^^^^^^^^^^ cannot infer type for mutable reference `&'a mut Bar`
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_95230`)
|
||||
note: required by a bound in `Bar`
|
||||
--> $DIR/issue-95230.rs:9:13
|
||||
|
|
||||
@ -15,4 +16,4 @@ LL | for<'a> &'a mut Self:;
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
@ -13,7 +13,7 @@ fn needs_bar<S: Bar>() {}
|
||||
|
||||
fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
|
||||
needs_bar::<T::Assoc1>();
|
||||
//~^ ERROR type annotations needed
|
||||
//~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,10 +1,10 @@
|
||||
error[E0283]: type annotations needed: cannot satisfy `<T as Foo1>::Assoc1: Bar`
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
|
||||
--> $DIR/recursive-self-normalization-2.rs:15:5
|
||||
|
|
||||
LL | needs_bar::<T::Assoc1>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: cannot satisfy `<T as Foo1>::Assoc1: Bar`
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
|
||||
note: required by a bound in `needs_bar`
|
||||
--> $DIR/recursive-self-normalization-2.rs:12:17
|
||||
|
|
||||
@ -13,4 +13,4 @@ LL | fn needs_bar<S: Bar>() {}
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
@ -9,7 +9,7 @@ fn needs_bar<S: Bar>() {}
|
||||
|
||||
fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
|
||||
needs_bar::<T::Assoc>();
|
||||
//~^ ERROR type annotations needed
|
||||
//~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,10 +1,10 @@
|
||||
error[E0283]: type annotations needed: cannot satisfy `<T as Foo>::Assoc: Bar`
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
|
||||
--> $DIR/recursive-self-normalization.rs:11:5
|
||||
|
|
||||
LL | needs_bar::<T::Assoc>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: cannot satisfy `<T as Foo>::Assoc: Bar`
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
|
||||
note: required by a bound in `needs_bar`
|
||||
--> $DIR/recursive-self-normalization.rs:8:17
|
||||
|
|
||||
@ -13,4 +13,4 @@ LL | fn needs_bar<S: Bar>() {}
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
Loading…
Reference in New Issue
Block a user