Normalize projection bounds when considering candidates

This unfortunately requires some winnowing hacks to avoid
now ambiguous candidates.
This commit is contained in:
Matthew Jasper
2020-07-24 19:10:22 +01:00
parent cfee49593d
commit 34e5a4992c
16 changed files with 390 additions and 256 deletions

View File

@@ -137,18 +137,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let candidate = candidate_predicate
.to_opt_poly_trait_ref()
.expect("projection candidate is not a trait predicate");
let mut obligations = self
.infcx
.at(&obligation.cause, obligation.param_env)
.sup(obligation.predicate.to_poly_trait_ref(), candidate)
.map(|InferOk { obligations, .. }| obligations)
.unwrap_or_else(|_| {
bug!(
"Projection bound `{:?}` was applicable to `{:?}` but now is not",
candidate,
obligation
);
});
let Normalized { value: candidate, mut obligations } = normalize_with_depth(
self,
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth + 1,
&candidate,
);
obligations.extend(
self.infcx
.at(&obligation.cause, obligation.param_env)
.sup(obligation.predicate.to_poly_trait_ref(), candidate)
.map(|InferOk { obligations, .. }| obligations)
.unwrap_or_else(|_| {
bug!(
"Projection bound `{:?}` was applicable to `{:?}` but now is not",
candidate,
obligation
);
}),
);
// Require that the projection is well-formed.
let self_ty = self.infcx.replace_bound_vars_with_placeholders(&bound_self_ty);
let self_ty = normalize_with_depth_to(