Report overflows gracefully with new solver
This commit is contained in:
parent
2a198c7f62
commit
05a6daab84
14 changed files with 75 additions and 27 deletions
|
@ -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>> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue