directly contain PredicateAtom
in PredicateKind::ForAll
This commit is contained in:
parent
d8cf8ba5f7
commit
cd9743b4d4
10 changed files with 162 additions and 179 deletions
|
@ -531,11 +531,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
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
|
||||
|
|
|
@ -201,21 +201,21 @@ impl FlagComputation {
|
|||
}
|
||||
}
|
||||
|
||||
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::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);
|
||||
}
|
||||
|
@ -249,7 +249,6 @@ impl FlagComputation {
|
|||
self.add_const(expected);
|
||||
self.add_const(found);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1053,8 +1053,9 @@ impl<'tcx> Predicate<'tcx> {
|
|||
///
|
||||
/// 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,
|
||||
}
|
||||
}
|
||||
|
@ -1066,33 +1067,17 @@ impl<'tcx> Predicate<'tcx> {
|
|||
/// 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> {
|
||||
|
@ -1114,7 +1099,7 @@ 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>),
|
||||
}
|
||||
|
@ -1162,6 +1147,22 @@ pub enum 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
|
||||
|
@ -1249,11 +1250,7 @@ impl<'tcx> Predicate<'tcx> {
|
|||
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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1381,6 +1378,7 @@ impl ToPredicate<'tcx> for PredicateKind<'tcx> {
|
|||
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))
|
||||
}
|
||||
}
|
||||
|
@ -1408,9 +1406,7 @@ impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitPredicate<'tcx>> {
|
|||
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)
|
||||
}
|
||||
|
@ -1423,9 +1419,7 @@ impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'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)
|
||||
}
|
||||
|
@ -1438,7 +1432,7 @@ impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'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)
|
||||
}
|
||||
|
@ -1450,9 +1444,7 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'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)),
|
||||
)
|
||||
ty::PredicateKind::ForAll(self.map_bound(|proj| PredicateAtom::Projection(proj)))
|
||||
.to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2013,7 +2013,13 @@ define_print_and_forward_display! {
|
|||
|
||||
ty::Predicate<'tcx> {
|
||||
match self.kind() {
|
||||
&ty::PredicateKind::Atom(atom) => match atom {
|
||||
&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 "));
|
||||
|
@ -2048,10 +2054,6 @@ define_print_and_forward_display! {
|
|||
write("`"))
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::ForAll(binder) => {
|
||||
p!(print(binder))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GenericArg<'tcx> {
|
||||
|
|
|
@ -6,6 +6,7 @@ use rustc_errors::ErrorReported;
|
|||
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;
|
||||
|
||||
|
|
|
@ -93,12 +93,8 @@ pub fn predicate_obligations<'a, 'tcx>(
|
|||
) -> 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);
|
||||
}
|
||||
&ty::PredicateKind::Atom(atom) => match atom {
|
||||
match predicate.skip_binders() {
|
||||
ty::PredicateAtom::Trait(t, _) => {
|
||||
wf.compute_trait_ref(&t.trait_ref, Elaborate::None);
|
||||
}
|
||||
|
@ -131,7 +127,6 @@ pub fn predicate_obligations<'a, 'tcx>(
|
|||
wf.compute(c1.into());
|
||||
wf.compute(c2.into());
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
wf.normalize()
|
||||
|
|
|
@ -798,11 +798,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
// 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
|
||||
{
|
||||
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)),
|
||||
ty::Param(ref p) if *p == param_ty => {
|
||||
Some(ty::Binder::bind(trait_predicate.trait_ref))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -815,7 +818,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
| 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);
|
||||
|
|
|
@ -2939,9 +2939,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
|
|||
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))
|
||||
|
@ -5373,7 +5371,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
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);
|
||||
|
||||
|
|
|
@ -1961,7 +1961,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
|
|||
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,
|
||||
))
|
||||
|
@ -1979,8 +1978,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
|
|||
}
|
||||
_ => 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)
|
||||
}))
|
||||
|
@ -2111,7 +2109,6 @@ fn predicates_from_bound<'tcx>(
|
|||
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)]
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use rustc_hir as hir;
|
|||
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;
|
||||
|
||||
|
@ -90,7 +90,6 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CratePredica
|
|||
match kind1.unpack() {
|
||||
GenericArgKind::Type(ty1) => Some((
|
||||
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty1, region2))
|
||||
.to_predicate(tcx)
|
||||
.potentially_quantified(tcx, ty::PredicateKind::ForAll),
|
||||
span,
|
||||
)),
|
||||
|
@ -98,7 +97,6 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CratePredica
|
|||
ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(
|
||||
region1, region2,
|
||||
))
|
||||
.to_predicate(tcx)
|
||||
.potentially_quantified(tcx, ty::PredicateKind::ForAll),
|
||||
span,
|
||||
)),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue