let predicate = match k1.unpack() {
GenericArgKind::Lifetime(r1) => {
ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r1, r2))
- .to_predicate(self.tcx)
}
GenericArgKind::Type(t1) => {
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(t1, r2))
- .to_predicate(self.tcx)
}
GenericArgKind::Const(..) => {
// Consts cannot outlive one another, so we don't expect to
}
}
- fn add_predicate(&mut self, pred: ty::Predicate<'_>) {
- self.add_flags(pred.inner.flags);
- self.add_exclusive_binder(pred.inner.outer_exclusive_binder);
- }
-
fn add_predicate_kind(&mut self, kind: &ty::PredicateKind<'_>) {
match kind {
ty::PredicateKind::ForAll(binder) => {
let mut computation = FlagComputation::new();
- computation.add_predicate(binder.skip_binder());
+ computation.add_predicate_atom(binder.skip_binder());
self.add_bound_computation(computation);
}
- &ty::PredicateKind::Atom(atom) => match atom {
- ty::PredicateAtom::Trait(trait_pred, _constness) => {
- self.add_substs(trait_pred.trait_ref.substs);
- }
- ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
- self.add_region(a);
- self.add_region(b);
- }
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, region)) => {
- self.add_ty(ty);
- self.add_region(region);
- }
- ty::PredicateAtom::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
- self.add_ty(a);
- self.add_ty(b);
- }
- ty::PredicateAtom::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
- self.add_projection_ty(projection_ty);
- self.add_ty(ty);
- }
- ty::PredicateAtom::WellFormed(arg) => {
- self.add_substs(slice::from_ref(&arg));
- }
- ty::PredicateAtom::ObjectSafe(_def_id) => {}
- ty::PredicateAtom::ClosureKind(_def_id, substs, _kind) => {
- self.add_substs(substs);
- }
- ty::PredicateAtom::ConstEvaluatable(_def_id, substs) => {
- self.add_substs(substs);
- }
- ty::PredicateAtom::ConstEquate(expected, found) => {
- self.add_const(expected);
- self.add_const(found);
- }
- },
+ &ty::PredicateKind::Atom(atom) => self.add_predicate_atom(atom),
+ }
+ }
+
+ fn add_predicate_atom(&mut self, atom: ty::PredicateAtom<'_>) {
+ match atom {
+ ty::PredicateAtom::Trait(trait_pred, _constness) => {
+ self.add_substs(trait_pred.trait_ref.substs);
+ }
+ ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
+ self.add_region(a);
+ self.add_region(b);
+ }
+ ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, region)) => {
+ self.add_ty(ty);
+ self.add_region(region);
+ }
+ ty::PredicateAtom::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
+ self.add_ty(a);
+ self.add_ty(b);
+ }
+ ty::PredicateAtom::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
+ self.add_projection_ty(projection_ty);
+ self.add_ty(ty);
+ }
+ ty::PredicateAtom::WellFormed(arg) => {
+ self.add_substs(slice::from_ref(&arg));
+ }
+ ty::PredicateAtom::ObjectSafe(_def_id) => {}
+ ty::PredicateAtom::ClosureKind(_def_id, substs, _kind) => {
+ self.add_substs(substs);
+ }
+ ty::PredicateAtom::ConstEvaluatable(_def_id, substs) => {
+ self.add_substs(substs);
+ }
+ ty::PredicateAtom::ConstEquate(expected, found) => {
+ self.add_const(expected);
+ self.add_const(found);
+ }
}
}
///
/// Note that this method panics in case this predicate has unbound variables.
pub fn skip_binders(self) -> PredicateAtom<'tcx> {
+ // TODO no_escaping_vars
match self.kind() {
- &PredicateKind::ForAll(binder) => binder.skip_binder().skip_binders(),
+ &PredicateKind::ForAll(binder) => binder.skip_binder(),
&ty::PredicateKind::Atom(atom) => atom,
}
}
/// to end up at the wrong binding level.
pub fn skip_binders_unchecked(self) -> PredicateAtom<'tcx> {
match self.kind() {
- &PredicateKind::ForAll(binder) => binder.skip_binder().skip_binders(),
+ &PredicateKind::ForAll(binder) => binder.skip_binder(),
&ty::PredicateKind::Atom(atom) => atom,
}
}
pub fn bound_atom(self, tcx: TyCtxt<'tcx>) -> Binder<PredicateAtom<'tcx>> {
match self.kind() {
- &PredicateKind::ForAll(binder) => binder.map_bound(|inner| match inner.kind() {
- ty::PredicateKind::ForAll(_) => bug!("unexpect forall"),
- &ty::PredicateKind::Atom(atom) => atom,
- }),
+ &PredicateKind::ForAll(binder) => binder,
&ty::PredicateKind::Atom(atom) => Binder::wrap_nonbinding(tcx, atom),
}
}
-
- /// Wraps `self` with the given qualifier if this predicate has any unbound variables.
- pub fn potentially_quantified(
- self,
- tcx: TyCtxt<'tcx>,
- qualifier: impl FnOnce(Binder<Predicate<'tcx>>) -> PredicateKind<'tcx>,
- ) -> Predicate<'tcx> {
- if self.has_escaping_bound_vars() {
- qualifier(Binder::bind(self)).to_predicate(tcx)
- } else {
- self
- }
- }
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
#[derive(HashStable, TypeFoldable)]
pub enum PredicateKind<'tcx> {
/// `for<'a>: ...`
- ForAll(Binder<Predicate<'tcx>>),
+ ForAll(Binder<PredicateAtom<'tcx>>),
Atom(PredicateAtom<'tcx>),
}
ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>),
}
+impl<'tcx> PredicateAtom<'tcx> {
+ /// Wraps `self` with the given qualifier if this predicate has any unbound variables.
+ pub fn potentially_quantified(
+ self,
+ tcx: TyCtxt<'tcx>,
+ qualifier: impl FnOnce(Binder<PredicateAtom<'tcx>>) -> PredicateKind<'tcx>,
+ ) -> Predicate<'tcx> {
+ if self.has_escaping_bound_vars() {
+ qualifier(Binder::bind(self))
+ } else {
+ PredicateKind::Atom(self)
+ }
+ .to_predicate(tcx)
+ }
+}
+
/// The crate outlives map is computed during typeck and contains the
/// outlives of every item in the local crate. You should not use it
/// directly, because to do so will make your pass dependent on the
let substs = trait_ref.skip_binder().substs;
let pred = self.skip_binders();
let new = pred.subst(tcx, substs);
- if new != pred {
- new.to_predicate(tcx).potentially_quantified(tcx, PredicateKind::ForAll)
- } else {
- self
- }
+ if new != pred { new.potentially_quantified(tcx, PredicateKind::ForAll) } else { self }
}
}
impl ToPredicate<'tcx> for PredicateAtom<'tcx> {
#[inline(always)]
fn to_predicate(&self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ debug_assert!(!self.has_escaping_bound_vars(), "excaping bound vars for {:?}", self);
tcx.mk_predicate(ty::PredicateKind::Atom(*self))
}
}
ty::PredicateAtom::Trait(pred, self.constness).to_predicate(tcx)
} else {
ty::PredicateKind::ForAll(
- self.value.map_bound(|pred| {
- ty::PredicateAtom::Trait(pred, self.constness).to_predicate(tcx)
- }),
+ self.value.map_bound(|pred| ty::PredicateAtom::Trait(pred, self.constness)),
)
.to_predicate(tcx)
}
PredicateAtom::RegionOutlives(outlives).to_predicate(tcx)
} else {
ty::PredicateKind::ForAll(
- self.map_bound(|outlives| {
- PredicateAtom::RegionOutlives(outlives).to_predicate(tcx)
- }),
+ self.map_bound(|outlives| PredicateAtom::RegionOutlives(outlives)),
)
.to_predicate(tcx)
}
PredicateAtom::TypeOutlives(outlives).to_predicate(tcx)
} else {
ty::PredicateKind::ForAll(
- self.map_bound(|outlives| PredicateAtom::TypeOutlives(outlives).to_predicate(tcx)),
+ self.map_bound(|outlives| PredicateAtom::TypeOutlives(outlives)),
)
.to_predicate(tcx)
}
if let Some(proj) = self.no_bound_vars() {
PredicateAtom::Projection(proj).to_predicate(tcx)
} else {
- ty::PredicateKind::ForAll(
- self.map_bound(|proj| PredicateAtom::Projection(proj).to_predicate(tcx)),
- )
- .to_predicate(tcx)
+ ty::PredicateKind::ForAll(self.map_bound(|proj| PredicateAtom::Projection(proj)))
+ .to_predicate(tcx)
}
}
}
ty::Predicate<'tcx> {
match self.kind() {
- &ty::PredicateKind::Atom(atom) => match atom {
- ty::PredicateAtom::Trait(ref data, constness) => {
- if let hir::Constness::Const = constness {
- p!(write("const "));
- }
- p!(print(data))
- }
- ty::PredicateAtom::Subtype(predicate) => p!(print(predicate)),
- ty::PredicateAtom::RegionOutlives(predicate) => p!(print(predicate)),
- ty::PredicateAtom::TypeOutlives(predicate) => p!(print(predicate)),
- ty::PredicateAtom::Projection(predicate) => p!(print(predicate)),
- ty::PredicateAtom::WellFormed(arg) => p!(print(arg), write(" well-formed")),
- ty::PredicateAtom::ObjectSafe(trait_def_id) => {
- p!(write("the trait `"),
- print_def_path(trait_def_id, &[]),
- write("` is object-safe"))
- }
- ty::PredicateAtom::ClosureKind(closure_def_id, _closure_substs, kind) => {
- p!(write("the closure `"),
- print_value_path(closure_def_id, &[]),
- write("` implements the trait `{}`", kind))
- }
- ty::PredicateAtom::ConstEvaluatable(def, substs) => {
- p!(write("the constant `"),
- print_value_path(def.did, substs),
- write("` can be evaluated"))
- }
- ty::PredicateAtom::ConstEquate(c1, c2) => {
- p!(write("the constant `"),
- print(c1),
- write("` equals `"),
- print(c2),
- write("`"))
+ &ty::PredicateKind::Atom(atom) => p!(print(atom)),
+ ty::PredicateKind::ForAll(binder) => p!(print(binder)),
+ }
+ }
+
+ ty::PredicateAtom<'tcx> {
+ match *self {
+ ty::PredicateAtom::Trait(ref data, constness) => {
+ if let hir::Constness::Const = constness {
+ p!(write("const "));
}
- }
- ty::PredicateKind::ForAll(binder) => {
- p!(print(binder))
+ p!(print(data))
+ }
+ ty::PredicateAtom::Subtype(predicate) => p!(print(predicate)),
+ ty::PredicateAtom::RegionOutlives(predicate) => p!(print(predicate)),
+ ty::PredicateAtom::TypeOutlives(predicate) => p!(print(predicate)),
+ ty::PredicateAtom::Projection(predicate) => p!(print(predicate)),
+ ty::PredicateAtom::WellFormed(arg) => p!(print(arg), write(" well-formed")),
+ ty::PredicateAtom::ObjectSafe(trait_def_id) => {
+ p!(write("the trait `"),
+ print_def_path(trait_def_id, &[]),
+ write("` is object-safe"))
+ }
+ ty::PredicateAtom::ClosureKind(closure_def_id, _closure_substs, kind) => {
+ p!(write("the closure `"),
+ print_value_path(closure_def_id, &[]),
+ write("` implements the trait `{}`", kind))
+ }
+ ty::PredicateAtom::ConstEvaluatable(def, substs) => {
+ p!(write("the constant `"),
+ print_value_path(def.did, substs),
+ write("` can be evaluated"))
+ }
+ ty::PredicateAtom::ConstEquate(c1, c2) => {
+ p!(write("the constant `"),
+ print(c1),
+ write("` equals `"),
+ print(c2),
+ write("`"))
}
}
}
use rustc_infer::traits::{PolyTraitObligation, TraitEngine, TraitEngineExt as _};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::error::ExpectedFound;
+use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::{self, Binder, Const, Ty, TypeFoldable};
use std::marker::PhantomData;
) -> Vec<traits::PredicateObligation<'tcx>> {
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
- match predicate.kind() {
- ty::PredicateKind::ForAll(binder) => {
- // It's ok to skip the binder here because wf code is prepared for it
- return predicate_obligations(infcx, param_env, body_id, binder.skip_binder(), span);
+ // It's ok to skip the binder here because wf code is prepared for it
+ match predicate.skip_binders() {
+ ty::PredicateAtom::Trait(t, _) => {
+ wf.compute_trait_ref(&t.trait_ref, Elaborate::None);
}
- &ty::PredicateKind::Atom(atom) => match atom {
- ty::PredicateAtom::Trait(t, _) => {
- wf.compute_trait_ref(&t.trait_ref, Elaborate::None);
- }
- ty::PredicateAtom::RegionOutlives(..) => {}
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
- wf.compute(ty.into());
- }
- ty::PredicateAtom::Projection(t) => {
- wf.compute_projection(t.projection_ty);
- wf.compute(t.ty.into());
- }
- ty::PredicateAtom::WellFormed(arg) => {
- wf.compute(arg);
- }
- ty::PredicateAtom::ObjectSafe(_) => {}
- ty::PredicateAtom::ClosureKind(..) => {}
- ty::PredicateAtom::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ }) => {
- wf.compute(a.into());
- wf.compute(b.into());
- }
- ty::PredicateAtom::ConstEvaluatable(def, substs) => {
- let obligations = wf.nominal_obligations(def.did, substs);
- wf.out.extend(obligations);
+ ty::PredicateAtom::RegionOutlives(..) => {}
+ ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
+ wf.compute(ty.into());
+ }
+ ty::PredicateAtom::Projection(t) => {
+ wf.compute_projection(t.projection_ty);
+ wf.compute(t.ty.into());
+ }
+ ty::PredicateAtom::WellFormed(arg) => {
+ wf.compute(arg);
+ }
+ ty::PredicateAtom::ObjectSafe(_) => {}
+ ty::PredicateAtom::ClosureKind(..) => {}
+ ty::PredicateAtom::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ }) => {
+ wf.compute(a.into());
+ wf.compute(b.into());
+ }
+ ty::PredicateAtom::ConstEvaluatable(def, substs) => {
+ let obligations = wf.nominal_obligations(def.did, substs);
+ wf.out.extend(obligations);
- for arg in substs.iter() {
- wf.compute(arg);
- }
- }
- ty::PredicateAtom::ConstEquate(c1, c2) => {
- wf.compute(c1.into());
- wf.compute(c2.into());
+ for arg in substs.iter() {
+ wf.compute(arg);
}
- },
+ }
+ ty::PredicateAtom::ConstEquate(c1, c2) => {
+ wf.compute(c1.into());
+ wf.compute(c2.into());
+ }
}
wf.normalize()
// FIXME: do we want to commit to this behavior for param bounds?
debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty);
- let bounds = self.param_env.caller_bounds().iter().map(ty::Predicate::skip_binders).filter_map(|predicate| match predicate
- {
- ty::PredicateAtom::Trait(trait_predicate, _) => {
- match trait_predicate.trait_ref.self_ty().kind {
- ty::Param(ref p) if *p == param_ty => Some(ty::Binder::bind(trait_predicate.trait_ref)),
- _ => None,
- }
- }
- ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::Projection(..)
- | ty::PredicateAtom::RegionOutlives(..)
- | ty::PredicateAtom::WellFormed(..)
- | ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::TypeOutlives(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..) => None,
- });
+ let bounds =
+ self.param_env.caller_bounds().iter().map(ty::Predicate::skip_binders).filter_map(
+ |predicate| match predicate {
+ ty::PredicateAtom::Trait(trait_predicate, _) => {
+ match trait_predicate.trait_ref.self_ty().kind {
+ ty::Param(ref p) if *p == param_ty => {
+ Some(ty::Binder::bind(trait_predicate.trait_ref))
+ }
+ _ => None,
+ }
+ }
+ ty::PredicateAtom::Subtype(..)
+ | ty::PredicateAtom::Projection(..)
+ | ty::PredicateAtom::RegionOutlives(..)
+ | ty::PredicateAtom::WellFormed(..)
+ | ty::PredicateAtom::ObjectSafe(..)
+ | ty::PredicateAtom::ClosureKind(..)
+ | ty::PredicateAtom::TypeOutlives(..)
+ | ty::PredicateAtom::ConstEvaluatable(..)
+ | ty::PredicateAtom::ConstEquate(..) => None,
+ },
+ );
self.elaborate_bounds(bounds, |this, poly_trait_ref, item| {
let trait_ref = this.erase_late_bound_regions(&poly_trait_ref);
predicates: tcx.arena.alloc_from_iter(
self.param_env.caller_bounds().iter().filter_map(|predicate| {
match predicate.skip_binders() {
- ty::PredicateAtom::Trait(data, _)
- if data.self_ty().is_param(index) =>
- {
+ ty::PredicateAtom::Trait(data, _) if data.self_ty().is_param(index) => {
// HACK(eddyb) should get the original `Span`.
let span = tcx.def_span(def_id);
Some((predicate, span))
projection_ty,
ty: expected,
})
- .to_predicate(self.tcx)
.potentially_quantified(self.tcx, ty::PredicateKind::ForAll);
let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
let region = AstConv::ast_region_to_region(&icx, lifetime, None);
predicates.push((
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, region))
- .to_predicate(tcx)
.potentially_quantified(tcx, ty::PredicateKind::ForAll),
lifetime.span,
))
}
_ => bug!(),
};
- let pred = ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r1, r2))
- .to_predicate(icx.tcx);
+ let pred = ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r1, r2));
(pred.potentially_quantified(icx.tcx, ty::PredicateKind::ForAll), span)
}))
hir::GenericBound::Outlives(ref lifetime) => {
let region = astconv.ast_region_to_region(lifetime, None);
let pred = ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
- .to_predicate(astconv.tcx())
.potentially_quantified(astconv.tcx(), ty::PredicateKind::ForAll);
vec![(pred, lifetime.span)]
}
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
+use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::Span;
match kind1.unpack() {
GenericArgKind::Type(ty1) => Some((
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty1, region2))
- .to_predicate(tcx)
.potentially_quantified(tcx, ty::PredicateKind::ForAll),
span,
)),
ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(
region1, region2,
))
- .to_predicate(tcx)
.potentially_quantified(tcx, ty::PredicateKind::ForAll),
span,
)),