Remove PredicateKind::Atom

This commit is contained in:
Jack Huey 2020-12-21 22:49:03 -05:00
parent 8a6518427e
commit 8278314a8b
12 changed files with 73 additions and 101 deletions

View File

@ -541,8 +541,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
span_bug!(cause.span, "unexpected const outlives {:?}", constraint);
}
};
let predicate =
predicate.rebind(atom).potentially_quantified(self.tcx, ty::PredicateKind::ForAll);
let predicate = predicate.rebind(atom).potentially_quantified(self.tcx);
Obligation::new(cause.clone(), param_env, predicate)
})

View File

@ -14,7 +14,6 @@ pub fn anonymize_predicate<'tcx>(
let new = ty::PredicateKind::ForAll(tcx.anonymize_late_bound_regions(binder));
tcx.reuse_or_mk_predicate(pred, new)
}
ty::PredicateKind::Atom(_) => pred,
}
}

View File

@ -211,7 +211,6 @@ impl FlagComputation {
computation.add_predicate_atom(atom)
});
}
ty::PredicateKind::Atom(atom) => self.add_predicate_atom(atom),
}
}

View File

@ -1037,7 +1037,7 @@ crate struct PredicateInner<'tcx> {
}
#[cfg(target_arch = "x86_64")]
static_assert_size!(PredicateInner<'_>, 48);
static_assert_size!(PredicateInner<'_>, 40);
#[derive(Clone, Copy, Lift)]
pub struct Predicate<'tcx> {
@ -1074,10 +1074,6 @@ impl<'tcx> Predicate<'tcx> {
pub fn skip_binders(self) -> PredicateAtom<'tcx> {
match self.kind() {
&PredicateKind::ForAll(binder) => binder.skip_binder(),
&PredicateKind::Atom(atom) => {
debug_assert!(!atom.has_escaping_bound_vars());
atom
}
}
}
@ -1090,7 +1086,6 @@ impl<'tcx> Predicate<'tcx> {
pub fn skip_binders_unchecked(self) -> PredicateAtom<'tcx> {
match self.kind() {
&PredicateKind::ForAll(binder) => binder.skip_binder(),
&PredicateKind::Atom(atom) => atom,
}
}
@ -1099,19 +1094,14 @@ impl<'tcx> Predicate<'tcx> {
pub fn bound_atom(self) -> Binder<PredicateAtom<'tcx>> {
match self.kind() {
&PredicateKind::ForAll(binder) => binder,
&PredicateKind::Atom(atom) => {
debug_assert!(!atom.has_escaping_bound_vars());
Binder::dummy(atom)
}
}
}
/// Allows using a `Binder<PredicateAtom<'tcx>>` even if the given predicate previously
/// contained unbound variables by shifting these variables outwards.
pub fn bound_atom_with_opt_escaping(self, tcx: TyCtxt<'tcx>) -> Binder<PredicateAtom<'tcx>> {
pub fn bound_atom_with_opt_escaping(self, _tcx: TyCtxt<'tcx>) -> Binder<PredicateAtom<'tcx>> {
match self.kind() {
&PredicateKind::ForAll(binder) => binder,
&PredicateKind::Atom(atom) => Binder::wrap_nonbinding(tcx, atom),
}
}
}
@ -1136,7 +1126,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
pub enum PredicateKind<'tcx> {
/// `for<'a>: ...`
ForAll(Binder<PredicateAtom<'tcx>>),
Atom(PredicateAtom<'tcx>),
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
@ -1189,16 +1178,8 @@ pub enum PredicateAtom<'tcx> {
impl<'tcx> Binder<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> {
match self.no_bound_vars() {
Some(atom) => PredicateKind::Atom(atom),
None => qualifier(self),
}
.to_predicate(tcx)
pub fn potentially_quantified(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
PredicateKind::ForAll(self).to_predicate(tcx)
}
}
@ -1289,11 +1270,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 {
ty::Binder::bind(new).potentially_quantified(tcx, PredicateKind::ForAll)
} else {
self
}
if new != pred { ty::Binder::bind(new).potentially_quantified(tcx) } else { self }
}
}
@ -1425,7 +1402,7 @@ impl ToPredicate<'tcx> for PredicateAtom<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
debug_assert!(!self.has_escaping_bound_vars(), "escaping bound vars for {:?}", self);
tcx.mk_predicate(PredicateKind::Atom(self))
tcx.mk_predicate(PredicateKind::ForAll(Binder::dummy(self)))
}
}
@ -1450,27 +1427,25 @@ impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitPredicate<'tcx>> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.value
.map_bound(|value| PredicateAtom::Trait(value, self.constness))
.potentially_quantified(tcx, PredicateKind::ForAll)
.potentially_quantified(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(PredicateAtom::RegionOutlives)
.potentially_quantified(tcx, PredicateKind::ForAll)
self.map_bound(PredicateAtom::RegionOutlives).potentially_quantified(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(PredicateAtom::TypeOutlives)
.potentially_quantified(tcx, PredicateKind::ForAll)
self.map_bound(PredicateAtom::TypeOutlives).potentially_quantified(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(PredicateAtom::Projection).potentially_quantified(tcx, PredicateKind::ForAll)
self.map_bound(PredicateAtom::Projection).potentially_quantified(tcx)
}
}

View File

@ -2069,7 +2069,6 @@ define_print_and_forward_display! {
ty::Predicate<'tcx> {
match self.kind() {
&ty::PredicateKind::Atom(atom) => p!(print(atom)),
ty::PredicateKind::ForAll(binder) => p!(print(binder)),
}
}

View File

@ -232,7 +232,6 @@ impl fmt::Debug for ty::PredicateKind<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
ty::PredicateKind::ForAll(binder) => write!(f, "ForAll({:?})", binder),
ty::PredicateKind::Atom(atom) => write!(f, "{:?}", atom),
}
}
}
@ -486,7 +485,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> {
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
match self {
ty::PredicateKind::ForAll(binder) => tcx.lift(binder).map(ty::PredicateKind::ForAll),
ty::PredicateKind::Atom(atom) => tcx.lift(atom).map(ty::PredicateKind::Atom),
}
}
}

View File

@ -346,45 +346,47 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
let infcx = self.selcx.infcx();
match *obligation.predicate.kind() {
ty::PredicateKind::ForAll(binder) if binder.skip_binder().has_escaping_bound_vars() => {
match binder.skip_binder() {
// Evaluation will discard candidates using the leak check.
// This means we need to pass it the bound version of our
// predicate.
ty::PredicateAtom::Trait(trait_ref, _constness) => {
let trait_obligation = obligation.with(binder.rebind(trait_ref));
self.process_trait_obligation(
obligation,
trait_obligation,
&mut pending_obligation.stalled_on,
)
}
ty::PredicateAtom::Projection(data) => {
let project_obligation = obligation.with(binder.rebind(data));
self.process_projection_obligation(
project_obligation,
&mut pending_obligation.stalled_on,
)
}
ty::PredicateAtom::RegionOutlives(_)
| ty::PredicateAtom::TypeOutlives(_)
| ty::PredicateAtom::WellFormed(_)
| ty::PredicateAtom::ObjectSafe(_)
| ty::PredicateAtom::ClosureKind(..)
| ty::PredicateAtom::Subtype(_)
| ty::PredicateAtom::ConstEvaluatable(..)
| ty::PredicateAtom::ConstEquate(..) => {
let pred = infcx.replace_bound_vars_with_placeholders(binder);
ProcessResult::Changed(mk_pending(vec![
obligation.with(pred.to_predicate(self.selcx.tcx())),
]))
}
ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
}
}
ty::PredicateKind::ForAll(binder) => match binder.skip_binder() {
// Evaluation will discard candidates using the leak check.
// This means we need to pass it the bound version of our
// predicate.
ty::PredicateAtom::Trait(trait_ref, _constness) => {
let trait_obligation = obligation.with(binder.rebind(trait_ref));
self.process_trait_obligation(
obligation,
trait_obligation,
&mut pending_obligation.stalled_on,
)
}
ty::PredicateAtom::Projection(data) => {
let project_obligation = obligation.with(binder.rebind(data));
self.process_projection_obligation(
project_obligation,
&mut pending_obligation.stalled_on,
)
}
ty::PredicateAtom::RegionOutlives(_)
| ty::PredicateAtom::TypeOutlives(_)
| ty::PredicateAtom::WellFormed(_)
| ty::PredicateAtom::ObjectSafe(_)
| ty::PredicateAtom::ClosureKind(..)
| ty::PredicateAtom::Subtype(_)
| ty::PredicateAtom::ConstEvaluatable(..)
| ty::PredicateAtom::ConstEquate(..) => {
let pred = infcx.replace_bound_vars_with_placeholders(binder);
ProcessResult::Changed(mk_pending(vec![
obligation.with(pred.to_predicate(self.selcx.tcx())),
]))
}
ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
},
ty::PredicateKind::Atom(atom) => match atom {
ty::PredicateAtom::Trait(data, _) => {
let trait_obligation = obligation.with(Binder::dummy(data));

View File

@ -95,8 +95,12 @@ fn compute_implied_outlives_bounds<'tcx>(
implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
assert!(!obligation.has_escaping_bound_vars());
match obligation.predicate.kind() {
&ty::PredicateKind::ForAll(..) => vec![],
&ty::PredicateKind::Atom(atom) => match atom {
&ty::PredicateKind::ForAll(binder)
if binder.skip_binder().has_escaping_bound_vars() =>
{
vec![]
}
&ty::PredicateKind::ForAll(binder) => match binder.skip_binder() {
ty::PredicateAtom::Trait(..)
| ty::PredicateAtom::Subtype(..)
| ty::PredicateAtom::Projection(..)

View File

@ -1949,10 +1949,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
let predicate = ty::Binder::bind(ty::PredicateAtom::TypeOutlives(
ty::OutlivesPredicate(ty, re_root_empty),
));
predicates.insert((
predicate.potentially_quantified(tcx, ty::PredicateKind::ForAll),
span,
));
predicates.insert((predicate.potentially_quantified(tcx), span));
}
}
@ -1996,7 +1993,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
ty::Binder::bind(ty::PredicateAtom::TypeOutlives(
ty::OutlivesPredicate(ty, region),
))
.potentially_quantified(tcx, ty::PredicateKind::ForAll),
.potentially_quantified(tcx),
lifetime.span,
));
}

View File

@ -31,13 +31,11 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate
let mut pred: Vec<String> = predicates
.iter()
.map(|(out_pred, _)| match out_pred.kind() {
ty::PredicateKind::Atom(ty::PredicateAtom::RegionOutlives(p)) => {
p.to_string()
}
ty::PredicateKind::Atom(ty::PredicateAtom::TypeOutlives(p)) => {
p.to_string()
}
err => bug!("unexpected predicate {:?}", err),
ty::PredicateKind::ForAll(binder) => match binder.skip_binder() {
ty::PredicateAtom::RegionOutlives(p) => p.to_string(),
ty::PredicateAtom::TypeOutlives(p) => p.to_string(),
err => bug!("unexpected predicate {:?}", err),
},
})
.collect();
pred.sort();

View File

@ -1,4 +1,4 @@
error: cannot specialize on `ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,))`
error: cannot specialize on `ForAll(Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,))))`
--> $DIR/repeated_projection_type.rs:19:1
|
LL | / impl<I, V: Id<This = (I,)>> X for V {

View File

@ -115,13 +115,15 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
.filter(|p| !p.is_global())
.filter_map(|obligation| {
// Note that we do not want to deal with qualified predicates here.
if let ty::PredicateKind::Atom(ty::PredicateAtom::Trait(pred, _)) = obligation.predicate.kind() {
if pred.def_id() == sized_trait {
return None;
let ty::PredicateKind::ForAll(binder) = obligation.predicate.kind();
match binder.skip_binder() {
ty::PredicateAtom::Trait(pred, _) if !binder.has_escaping_bound_vars() => {
if pred.def_id() == sized_trait {
return None;
}
Some(pred)
}
Some(pred)
} else {
None
_ => None,
}
})
.collect::<Vec<_>>();