Fix bugs in evaluating WellFormed predicates
- List the nestsed obligations in an order that works with the single pass used by evaluation - Propagate recursion depth correctly
This commit is contained in:
parent
f52b2d8890
commit
bc08b791bc
8 changed files with 117 additions and 42 deletions
|
@ -20,6 +20,7 @@ pub fn obligations<'a, 'tcx>(
|
|||
infcx: &InferCtxt<'a, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body_id: hir::HirId,
|
||||
recursion_depth: usize,
|
||||
arg: GenericArg<'tcx>,
|
||||
span: Span,
|
||||
) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
|
||||
|
@ -59,7 +60,8 @@ pub fn obligations<'a, 'tcx>(
|
|||
GenericArgKind::Lifetime(..) => return Some(Vec::new()),
|
||||
};
|
||||
|
||||
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
|
||||
let mut wf =
|
||||
WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth, item: None };
|
||||
wf.compute(arg);
|
||||
debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out);
|
||||
|
||||
|
@ -80,7 +82,8 @@ pub fn trait_obligations<'a, 'tcx>(
|
|||
span: Span,
|
||||
item: Option<&'tcx hir::Item<'tcx>>,
|
||||
) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item };
|
||||
let mut wf =
|
||||
WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth: 0, item };
|
||||
wf.compute_trait_ref(trait_ref, Elaborate::All);
|
||||
wf.normalize()
|
||||
}
|
||||
|
@ -92,7 +95,15 @@ pub fn predicate_obligations<'a, 'tcx>(
|
|||
predicate: ty::Predicate<'tcx>,
|
||||
span: Span,
|
||||
) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
|
||||
let mut wf = WfPredicates {
|
||||
infcx,
|
||||
param_env,
|
||||
body_id,
|
||||
span,
|
||||
out: vec![],
|
||||
recursion_depth: 0,
|
||||
item: None,
|
||||
};
|
||||
|
||||
// It's ok to skip the binder here because wf code is prepared for it
|
||||
match predicate.skip_binders() {
|
||||
|
@ -142,6 +153,7 @@ struct WfPredicates<'a, 'tcx> {
|
|||
body_id: hir::HirId,
|
||||
span: Span,
|
||||
out: Vec<traits::PredicateObligation<'tcx>>,
|
||||
recursion_depth: usize,
|
||||
item: Option<&'tcx hir::Item<'tcx>>,
|
||||
}
|
||||
|
||||
|
@ -249,19 +261,19 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
for mut obligation in self.out {
|
||||
assert!(!obligation.has_escaping_bound_vars());
|
||||
let mut selcx = traits::SelectionContext::new(infcx);
|
||||
let i = obligations.len();
|
||||
// Don't normalize the whole obligation, the param env is either
|
||||
// already normalized, or we're currently normalizing the
|
||||
// param_env. Either way we should only normalize the predicate.
|
||||
let normalized_predicate = traits::normalize_to(
|
||||
let normalized_predicate = traits::project::normalize_with_depth_to(
|
||||
&mut selcx,
|
||||
param_env,
|
||||
cause.clone(),
|
||||
self.recursion_depth,
|
||||
&obligation.predicate,
|
||||
&mut obligations,
|
||||
);
|
||||
obligation.predicate = normalized_predicate;
|
||||
obligations.insert(i, obligation);
|
||||
obligations.push(obligation);
|
||||
}
|
||||
obligations
|
||||
}
|
||||
|
@ -274,6 +286,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
debug!("compute_trait_ref obligations {:?}", obligations);
|
||||
let cause = self.cause(traits::MiscObligation);
|
||||
let param_env = self.param_env;
|
||||
let depth = self.recursion_depth;
|
||||
|
||||
let item = self.item;
|
||||
|
||||
|
@ -295,7 +308,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
&obligation.predicate,
|
||||
tcx.associated_items(trait_ref.def_id).in_definition_order(),
|
||||
);
|
||||
traits::Obligation::new(cause, param_env, obligation.predicate)
|
||||
traits::Obligation::with_depth(cause, depth, param_env, obligation.predicate)
|
||||
};
|
||||
|
||||
if let Elaborate::All = elaborate {
|
||||
|
@ -324,8 +337,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
new_cause.make_mut().span = self_ty.span;
|
||||
}
|
||||
}
|
||||
traits::Obligation::new(
|
||||
traits::Obligation::with_depth(
|
||||
new_cause,
|
||||
depth,
|
||||
param_env,
|
||||
ty::PredicateAtom::WellFormed(arg).to_predicate(tcx),
|
||||
)
|
||||
|
@ -363,6 +377,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
let tcx = self.tcx();
|
||||
let cause = self.cause(traits::MiscObligation);
|
||||
let param_env = self.param_env;
|
||||
let depth = self.recursion_depth;
|
||||
|
||||
self.out.extend(
|
||||
data.substs
|
||||
|
@ -372,8 +387,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
})
|
||||
.filter(|arg| !arg.has_escaping_bound_vars())
|
||||
.map(|arg| {
|
||||
traits::Obligation::new(
|
||||
traits::Obligation::with_depth(
|
||||
cause.clone(),
|
||||
depth,
|
||||
param_env,
|
||||
ty::PredicateKind::WellFormed(arg).to_predicate(tcx),
|
||||
)
|
||||
|
@ -388,8 +404,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
def_id: self.infcx.tcx.require_lang_item(LangItem::Sized, None),
|
||||
substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
|
||||
};
|
||||
self.out.push(traits::Obligation::new(
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
cause,
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
trait_ref.without_const().to_predicate(self.infcx.tcx),
|
||||
));
|
||||
|
@ -400,6 +417,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
fn compute(&mut self, arg: GenericArg<'tcx>) {
|
||||
let mut walker = arg.walk();
|
||||
let param_env = self.param_env;
|
||||
let depth = self.recursion_depth;
|
||||
while let Some(arg) = walker.next() {
|
||||
let ty = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => ty,
|
||||
|
@ -419,8 +437,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
let predicate = ty::PredicateAtom::ConstEvaluatable(def, substs)
|
||||
.to_predicate(self.tcx());
|
||||
let cause = self.cause(traits::MiscObligation);
|
||||
self.out.push(traits::Obligation::new(
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
cause,
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
predicate,
|
||||
));
|
||||
|
@ -435,8 +454,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
val: ty::ConstKind::Infer(resolved),
|
||||
..*constant
|
||||
});
|
||||
self.out.push(traits::Obligation::new(
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
cause,
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
ty::PredicateAtom::WellFormed(resolved_constant.into())
|
||||
.to_predicate(self.tcx()),
|
||||
|
@ -521,8 +541,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
// WfReference
|
||||
if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
|
||||
let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
|
||||
self.out.push(traits::Obligation::new(
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
cause,
|
||||
depth,
|
||||
param_env,
|
||||
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(rty, r))
|
||||
.to_predicate(self.tcx()),
|
||||
|
@ -612,8 +633,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
let component_traits = data.auto_traits().chain(data.principal_def_id());
|
||||
let tcx = self.tcx();
|
||||
self.out.extend(component_traits.map(|did| {
|
||||
traits::Obligation::new(
|
||||
traits::Obligation::with_depth(
|
||||
cause.clone(),
|
||||
depth,
|
||||
param_env,
|
||||
ty::PredicateAtom::ObjectSafe(did).to_predicate(tcx),
|
||||
)
|
||||
|
@ -638,8 +660,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
|
||||
// Not yet resolved, but we've made progress.
|
||||
let cause = self.cause(traits::MiscObligation);
|
||||
self.out.push(traits::Obligation::new(
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
cause,
|
||||
self.recursion_depth,
|
||||
param_env,
|
||||
ty::PredicateAtom::WellFormed(ty.into()).to_predicate(self.tcx()),
|
||||
));
|
||||
|
@ -676,7 +699,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
.zip(origins.into_iter().rev())
|
||||
.map(|((pred, span), origin_def_id)| {
|
||||
let cause = self.cause(traits::BindingObligation(origin_def_id, span));
|
||||
traits::Obligation::new(cause, self.param_env, pred)
|
||||
traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred)
|
||||
})
|
||||
.filter(|pred| !pred.has_escaping_bound_vars())
|
||||
.collect()
|
||||
|
@ -729,8 +752,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
|
||||
let outlives =
|
||||
ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound));
|
||||
self.out.push(traits::Obligation::new(
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
cause,
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
outlives.to_predicate(self.infcx.tcx),
|
||||
));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue