1
Fork 0

Auto merge of #77685 - jackh726:binder-map, r=lcnr

Use rebind instead of Binder::bind when possible

These are really only the easy places. I just searched for `Binder::bind` and replaced where it straightforward.

r? `@lcnr`
cc. `@nikomatsakis`
This commit is contained in:
bors 2020-10-17 10:28:52 +00:00
commit 6f0ea299cf
24 changed files with 194 additions and 139 deletions

View file

@ -1056,9 +1056,21 @@ impl<'tcx> Predicate<'tcx> {
}
}
/// Converts this to a `Binder<PredicateAtom<'tcx>>`. If the value was an
/// `Atom`, then it is not allowed to contain escaping bound vars.
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(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),

View file

@ -618,10 +618,9 @@ pub trait PrettyPrinter<'tcx>:
// may contain unbound variables. We therefore do this manually.
//
// FIXME(lcnr): Find out why exactly this is the case :)
if let ty::PredicateAtom::Trait(pred, _) =
predicate.bound_atom(self.tcx()).skip_binder()
{
let trait_ref = ty::Binder::bind(pred.trait_ref);
let bound_predicate = predicate.bound_atom_with_opt_escaping(self.tcx());
if let ty::PredicateAtom::Trait(pred, _) = bound_predicate.skip_binder() {
let trait_ref = bound_predicate.rebind(pred.trait_ref);
// Don't print +Sized, but rather +?Sized if absent.
if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
is_sized = true;

View file

@ -549,7 +549,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateAtom<'a> {
impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<T> {
type Lifted = ty::Binder<T::Lifted>;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(self.as_ref().skip_binder()).map(ty::Binder::bind)
tcx.lift(self.as_ref().skip_binder()).map(|v| self.rebind(v))
}
}

View file

@ -703,14 +703,16 @@ impl<'tcx> Binder<ExistentialPredicate<'tcx>> {
use crate::ty::ToPredicate;
match self.skip_binder() {
ExistentialPredicate::Trait(tr) => {
Binder(tr).with_self_ty(tcx, self_ty).without_const().to_predicate(tcx)
self.rebind(tr).with_self_ty(tcx, self_ty).without_const().to_predicate(tcx)
}
ExistentialPredicate::Projection(p) => {
Binder(p.with_self_ty(tcx, self_ty)).to_predicate(tcx)
self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx)
}
ExistentialPredicate::AutoTrait(did) => {
let trait_ref =
Binder(ty::TraitRef { def_id: did, substs: tcx.mk_substs_trait(self_ty, &[]) });
let trait_ref = self.rebind(ty::TraitRef {
def_id: did,
substs: tcx.mk_substs_trait(self_ty, &[]),
});
trait_ref.without_const().to_predicate(tcx)
}
}
@ -775,7 +777,7 @@ impl<'tcx> List<ExistentialPredicate<'tcx>> {
impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
pub fn principal(&self) -> Option<ty::Binder<ExistentialTraitRef<'tcx>>> {
self.skip_binder().principal().map(Binder::bind)
self.map_bound(|b| b.principal()).transpose()
}
pub fn principal_def_id(&self) -> Option<DefId> {
@ -858,8 +860,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
}
pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
// Note that we preserve binding levels
Binder(ty::TraitPredicate { trait_ref: self.skip_binder() })
self.map_bound(|trait_ref| ty::TraitPredicate { trait_ref })
}
}
@ -1001,6 +1002,19 @@ impl<T> Binder<T> {
Binder(f(self.0))
}
/// Wraps a `value` in a binder, using the same bound variables as the
/// current `Binder`. This should not be used if the new value *changes*
/// the bound variables. Note: the (old or new) value itself does not
/// necessarily need to *name* all the bound variables.
///
/// This currently doesn't do anything different than `bind`, because we
/// don't actually track bound vars. However, semantically, it is different
/// because bound vars aren't allowed to change here, whereas they are
/// in `bind`. This may be (debug) asserted in the future.
pub fn rebind<U>(&self, value: U) -> Binder<U> {
Binder(value)
}
/// Unwraps and returns the value within, but only if it contains
/// no bound vars at all. (In other words, if this binder --
/// and indeed any enclosing binder -- doesn't bind anything at