use rustc_data_structures::obligation_forest::ProcessResult;
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
-use rustc_errors::ErrorReported;
use rustc_infer::traits::ProjectionCacheKey;
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
use rustc_middle::mir::interpret::ErrorHandled;
use std::marker::PhantomData;
use super::const_evaluatable;
-use super::project;
+use super::project::{self, ProjectAndUnifyResult};
use super::select::SelectionContext;
use super::wf;
use super::CodeAmbiguity;
// Should this fulfillment context register type-lives-for-region
// obligations on its parent infcx? In some cases, region
// obligations are either already known to hold (normalization) or
- // hopefully verifed elsewhere (type-impls-bound), and therefore
+ // hopefully verified elsewhere (type-impls-bound), and therefore
// should not be checked.
//
// Note that if we are normalizing a type that we already
return ProcessResult::Unchanged;
}
- self.progress_changed_obligations(pending_obligation)
+ self.process_changed_obligations(pending_obligation)
}
fn process_backedge<'c, I>(
// actually uses this, so move this part of the code
// out of that loop.
#[inline(never)]
- fn progress_changed_obligations(
+ fn process_changed_obligations(
&mut self,
pending_obligation: &mut PendingPredicateObligation<'tcx>,
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
let obligation = &mut pending_obligation.obligation;
+ debug!(?obligation, "process_obligation pre-resolve");
+
if obligation.predicate.has_infer_types_or_consts() {
obligation.predicate =
self.selcx.infcx().resolve_vars_if_possible(obligation.predicate);
let infcx = self.selcx.infcx();
+ if obligation.predicate.has_projections() {
+ let mut obligations = Vec::new();
+ let predicate = crate::traits::project::try_normalize_with_depth_to(
+ self.selcx,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ obligation.predicate,
+ &mut obligations,
+ );
+ if predicate != obligation.predicate {
+ obligations.push(obligation.with(predicate));
+ return ProcessResult::Changed(mk_pending(obligations));
+ }
+ }
let binder = obligation.predicate.kind();
match binder.no_bound_vars() {
None => match binder.skip_binder() {
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
(c1.val(), c2.val())
{
- if infcx.try_unify_abstract_consts(a.shrink(), b.shrink()) {
+ if infcx.try_unify_abstract_consts(
+ a.shrink(),
+ b.shrink(),
+ obligation.param_env,
+ ) {
return ProcessResult::Changed(vec![]);
}
}
),
}
}
- (Err(ErrorHandled::Reported(ErrorReported)), _)
- | (_, Err(ErrorHandled::Reported(ErrorReported))) => ProcessResult::Error(
+ (Err(ErrorHandled::Reported(reported)), _)
+ | (_, Err(ErrorHandled::Reported(reported))) => ProcessResult::Error(
CodeSelectionError(SelectionError::NotConstEvaluatable(
- NotConstEvaluatable::Error(ErrorReported),
+ NotConstEvaluatable::Error(reported),
)),
),
(Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => {
}
match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
- Ok(Ok(Some(os))) => ProcessResult::Changed(mk_pending(os)),
- Ok(Ok(None)) => {
+ ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)),
+ ProjectAndUnifyResult::FailedNormalization => {
stalled_on.clear();
stalled_on.extend(substs_infer_vars(
self.selcx,
ProcessResult::Unchanged
}
// Let the caller handle the recursion
- Ok(Err(project::InProgress)) => ProcessResult::Changed(mk_pending(vec![
+ ProjectAndUnifyResult::Recursive => ProcessResult::Changed(mk_pending(vec![
project_obligation.with(project_obligation.predicate.to_predicate(tcx)),
])),
- Err(e) => ProcessResult::Error(CodeProjectionError(e)),
+ ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
+ ProcessResult::Error(CodeProjectionError(e))
+ }
}
}
}