Track bound vars
This commit is contained in:
parent
62a49c3bb8
commit
30187c81f6
33 changed files with 478 additions and 362 deletions
|
@ -124,6 +124,7 @@ where
|
|||
{
|
||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
||||
self.as_ref().skip_binder().hash_stable(hcx, hasher);
|
||||
self.bound_vars().hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -122,6 +122,7 @@ impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Ty<'tcx> {
|
|||
|
||||
impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Binder<'tcx, ty::PredicateKind<'tcx>> {
|
||||
fn encode(&self, e: &mut E) -> Result<(), E::Error> {
|
||||
self.bound_vars().encode(e)?;
|
||||
encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands)
|
||||
}
|
||||
}
|
||||
|
@ -228,16 +229,20 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
|
|||
|
||||
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<'tcx, ty::PredicateKind<'tcx>> {
|
||||
fn decode(decoder: &mut D) -> Result<ty::Binder<'tcx, ty::PredicateKind<'tcx>>, D::Error> {
|
||||
let bound_vars = Decodable::decode(decoder)?;
|
||||
// Handle shorthands first, if we have an usize > 0x80.
|
||||
Ok(ty::Binder::bind(if decoder.positioned_at_shorthand() {
|
||||
let pos = decoder.read_usize()?;
|
||||
assert!(pos >= SHORTHAND_OFFSET);
|
||||
let shorthand = pos - SHORTHAND_OFFSET;
|
||||
Ok(ty::Binder::bind_with_vars(
|
||||
if decoder.positioned_at_shorthand() {
|
||||
let pos = decoder.read_usize()?;
|
||||
assert!(pos >= SHORTHAND_OFFSET);
|
||||
let shorthand = pos - SHORTHAND_OFFSET;
|
||||
|
||||
decoder.with_position(shorthand, ty::PredicateKind::decode)?
|
||||
} else {
|
||||
ty::PredicateKind::decode(decoder)?
|
||||
}))
|
||||
decoder.with_position(shorthand, ty::PredicateKind::decode)?
|
||||
} else {
|
||||
ty::PredicateKind::decode(decoder)?
|
||||
},
|
||||
bound_vars,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -379,6 +384,13 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::N
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::BoundVariableKind> {
|
||||
fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
|
||||
let len = decoder.read_usize()?;
|
||||
Ok(decoder.tcx().mk_bound_variable_kinds((0..len).map(|_| Decodable::decode(decoder)))?)
|
||||
}
|
||||
}
|
||||
|
||||
impl_decodable_via_ref! {
|
||||
&'tcx ty::TypeckResults<'tcx>,
|
||||
&'tcx ty::List<Ty<'tcx>>,
|
||||
|
@ -387,7 +399,8 @@ impl_decodable_via_ref! {
|
|||
&'tcx mir::Body<'tcx>,
|
||||
&'tcx mir::UnsafetyCheckResult,
|
||||
&'tcx mir::BorrowCheckResult<'tcx>,
|
||||
&'tcx mir::coverage::CodeRegion
|
||||
&'tcx mir::coverage::CodeRegion,
|
||||
&'tcx ty::List<ty::BoundVariableKind>
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
|
@ -490,12 +503,14 @@ macro_rules! impl_binder_encode_decode {
|
|||
$(
|
||||
impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Binder<'tcx, $t> {
|
||||
fn encode(&self, e: &mut E) -> Result<(), E::Error> {
|
||||
self.bound_vars().encode(e)?;
|
||||
self.as_ref().skip_binder().encode(e)
|
||||
}
|
||||
}
|
||||
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<'tcx, $t> {
|
||||
fn decode(decoder: &mut D) -> Result<Self, D::Error> {
|
||||
Ok(ty::Binder::bind(Decodable::decode(decoder)?))
|
||||
let bound_vars = Decodable::decode(decoder)?;
|
||||
Ok(ty::Binder::bind_with_vars(Decodable::decode(decoder)?, bound_vars))
|
||||
}
|
||||
}
|
||||
)*
|
||||
|
|
|
@ -96,6 +96,7 @@ pub struct CtxtInterners<'tcx> {
|
|||
const_: InternedSet<'tcx, Const<'tcx>>,
|
||||
/// Const allocations.
|
||||
allocation: InternedSet<'tcx, Allocation>,
|
||||
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
|
||||
}
|
||||
|
||||
impl<'tcx> CtxtInterners<'tcx> {
|
||||
|
@ -114,6 +115,7 @@ impl<'tcx> CtxtInterners<'tcx> {
|
|||
place_elems: Default::default(),
|
||||
const_: Default::default(),
|
||||
allocation: Default::default(),
|
||||
bound_variable_kinds: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1624,6 +1626,7 @@ nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate
|
|||
nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
|
||||
nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
|
||||
nop_list_lift! {projs; ProjectionKind => ProjectionKind}
|
||||
nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind}
|
||||
|
||||
// This is the impl for `&'a InternalSubsts<'a>`.
|
||||
nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
|
||||
|
@ -2080,6 +2083,7 @@ slice_interners!(
|
|||
predicates: _intern_predicates(Predicate<'tcx>),
|
||||
projs: _intern_projs(ProjectionKind),
|
||||
place_elems: _intern_place_elems(PlaceElem<'tcx>),
|
||||
bound_variable_kinds: _intern_bound_variable_kinds(ty::BoundVariableKind),
|
||||
);
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
|
@ -2516,6 +2520,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) }
|
||||
}
|
||||
|
||||
pub fn intern_bound_variable_kinds(
|
||||
self,
|
||||
ts: &[ty::BoundVariableKind],
|
||||
) -> &'tcx List<ty::BoundVariableKind> {
|
||||
if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) }
|
||||
}
|
||||
|
||||
pub fn mk_fn_sig<I>(
|
||||
self,
|
||||
inputs: I,
|
||||
|
@ -2576,6 +2587,15 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.mk_substs(iter::once(self_ty.into()).chain(rest.iter().cloned()))
|
||||
}
|
||||
|
||||
pub fn mk_bound_variable_kinds<
|
||||
I: InternAs<[ty::BoundVariableKind], &'tcx List<ty::BoundVariableKind>>,
|
||||
>(
|
||||
self,
|
||||
iter: I,
|
||||
) -> I::Output {
|
||||
iter.intern_with(|xs| self.intern_bound_variable_kinds(xs))
|
||||
}
|
||||
|
||||
/// Walks upwards from `id` to find a node which might change lint levels with attributes.
|
||||
/// It stops at `bound` and just returns it if reached.
|
||||
pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId {
|
||||
|
|
|
@ -35,6 +35,7 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def_id::DefId;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::sso::SsoHashSet;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
use std::ops::ControlFlow;
|
||||
|
@ -702,10 +703,109 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
r
|
||||
})
|
||||
.0,
|
||||
self,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BoundVarsCollector<'tcx> {
|
||||
binder_index: ty::DebruijnIndex,
|
||||
vars: BTreeMap<u32, ty::BoundVariableKind>,
|
||||
// We may encounter the same variable at different levels of binding, so
|
||||
// this can't just be `Ty`
|
||||
visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
|
||||
}
|
||||
|
||||
impl<'tcx> BoundVarsCollector<'tcx> {
|
||||
pub fn new() -> Self {
|
||||
BoundVarsCollector {
|
||||
binder_index: ty::INNERMOST,
|
||||
vars: BTreeMap::new(),
|
||||
visited: SsoHashSet::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List<ty::BoundVariableKind> {
|
||||
let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or_else(|| 0);
|
||||
for i in 0..max {
|
||||
if let None = self.vars.get(&i) {
|
||||
panic!("Unknown variable: {:?}", i);
|
||||
}
|
||||
}
|
||||
|
||||
tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(
|
||||
&mut self,
|
||||
t: &Binder<'tcx, T>,
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
self.binder_index.shift_in(1);
|
||||
let result = t.super_visit_with(self);
|
||||
self.binder_index.shift_out(1);
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if t.outer_exclusive_binder < self.binder_index
|
||||
|| !self.visited.insert((self.binder_index, t))
|
||||
{
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
use std::collections::btree_map::Entry;
|
||||
match *t.kind() {
|
||||
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
|
||||
match self.vars.entry(bound_ty.var.as_u32()) {
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind));
|
||||
}
|
||||
Entry::Occupied(entry) => match entry.get() {
|
||||
ty::BoundVariableKind::Ty(_) => {}
|
||||
_ => bug!("Conflicting bound vars"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
use std::collections::btree_map::Entry;
|
||||
match r {
|
||||
ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind {
|
||||
ty::BrNamed(_def_id, _name) => {
|
||||
// FIXME
|
||||
}
|
||||
|
||||
ty::BrAnon(var) => match self.vars.entry(var) {
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(ty::BoundVariableKind::Region(br.kind));
|
||||
}
|
||||
Entry::Occupied(entry) => match entry.get() {
|
||||
ty::BoundVariableKind::Region(_) => {}
|
||||
_ => bug!("Conflicting bound vars"),
|
||||
},
|
||||
},
|
||||
|
||||
ty::BrEnv => {
|
||||
// FIXME
|
||||
}
|
||||
},
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
r.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Shifter
|
||||
//
|
||||
|
@ -907,57 +1007,6 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
|
|||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
struct FoundFlags;
|
||||
|
||||
crate struct CountBoundVars {
|
||||
crate outer_index: ty::DebruijnIndex,
|
||||
crate bound_tys: FxHashSet<ty::BoundTy>,
|
||||
crate bound_regions: FxHashSet<ty::BoundRegion>,
|
||||
crate bound_consts: FxHashSet<ty::BoundVar>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for CountBoundVars {
|
||||
type BreakTy = ();
|
||||
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(
|
||||
&mut self,
|
||||
t: &Binder<'tcx, T>,
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
self.outer_index.shift_in(1);
|
||||
let result = t.super_visit_with(self);
|
||||
self.outer_index.shift_out(1);
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match t.kind {
|
||||
ty::Bound(debruijn, ty) if debruijn == self.outer_index => {
|
||||
self.bound_tys.insert(ty);
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
_ => t.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match r {
|
||||
ty::ReLateBound(debruijn, re) if *debruijn == self.outer_index => {
|
||||
self.bound_regions.insert(*re);
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
_ => r.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match ct.val {
|
||||
ty::ConstKind::Bound(debruijn, c) if debruijn == self.outer_index => {
|
||||
self.bound_consts.insert(c);
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
_ => ct.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Optimize for checking for infer flags
|
||||
struct HasTypeFlagsVisitor {
|
||||
flags: ty::TypeFlags,
|
||||
|
|
|
@ -67,12 +67,12 @@ pub use self::sty::BoundRegionKind::*;
|
|||
pub use self::sty::RegionKind::*;
|
||||
pub use self::sty::TyKind::*;
|
||||
pub use self::sty::{
|
||||
Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, CanonicalPolyFnSig,
|
||||
ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion, ExistentialPredicate,
|
||||
ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, GeneratorSubsts,
|
||||
GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection, PolyExistentialTraitRef,
|
||||
PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef,
|
||||
TyKind, TypeAndMut, UpvarSubsts,
|
||||
Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind,
|
||||
CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion,
|
||||
ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig,
|
||||
GeneratorSubsts, GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection,
|
||||
PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind,
|
||||
RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts,
|
||||
};
|
||||
pub use self::trait_def::TraitDef;
|
||||
|
||||
|
@ -546,7 +546,7 @@ impl<'tcx> Predicate<'tcx> {
|
|||
let substs = trait_ref.skip_binder().substs;
|
||||
let pred = self.kind().skip_binder();
|
||||
let new = pred.subst(tcx, substs);
|
||||
tcx.reuse_or_mk_predicate(self, ty::Binder::bind(new))
|
||||
tcx.reuse_or_mk_predicate(self, ty::Binder::bind(new, tcx))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -460,8 +460,10 @@ where
|
|||
{
|
||||
type Lifted = ty::Binder<'tcx, T::Lifted>;
|
||||
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
// FIXME: need to lift inner values
|
||||
tcx.lift(self.skip_binder()).map(|v| ty::Binder::bind(v))
|
||||
let bound_vars = tcx.lift(self.bound_vars());
|
||||
tcx.lift(self.skip_binder())
|
||||
.zip(bound_vars)
|
||||
.map(|(value, vars)| ty::Binder::bind_with_vars(value, vars))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use self::TyKind::*;
|
||||
|
||||
use crate::infer::canonical::Canonical;
|
||||
use crate::ty::fold::BoundVarsCollector;
|
||||
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
|
||||
use crate::ty::InferTy::{self, *};
|
||||
use crate::ty::{
|
||||
|
@ -947,6 +948,14 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable)]
|
||||
pub enum BoundVariableKind {
|
||||
Ty(BoundTyKind),
|
||||
Region(BoundRegionKind),
|
||||
Const,
|
||||
}
|
||||
|
||||
/// Binder is a binder for higher-ranked lifetimes or types. It is part of the
|
||||
/// compiler's representation for things like `for<'a> Fn(&'a isize)`
|
||||
/// (which would be represented by the type `PolyTraitRef ==
|
||||
|
@ -957,7 +966,7 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
|
|||
///
|
||||
/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct Binder<'tcx, T>(T, u32, std::marker::PhantomData<&'tcx ()>);
|
||||
pub struct Binder<'tcx, T>(T, &'tcx List<BoundVariableKind>);
|
||||
|
||||
impl<'tcx, T> Binder<'tcx, T>
|
||||
where
|
||||
|
@ -969,48 +978,22 @@ where
|
|||
/// different binding level.
|
||||
pub fn dummy(value: T) -> Binder<'tcx, T> {
|
||||
debug_assert!(!value.has_escaping_bound_vars());
|
||||
Binder(value, 0, std::marker::PhantomData)
|
||||
Binder(value, ty::List::empty())
|
||||
}
|
||||
|
||||
/// Wraps `value` in a binder, binding higher-ranked vars (if any).
|
||||
pub fn bind(value: T) -> Binder<'tcx, T> {
|
||||
use crate::ty::fold::CountBoundVars;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
let mut counter = CountBoundVars {
|
||||
outer_index: ty::INNERMOST,
|
||||
bound_tys: FxHashSet::default(),
|
||||
bound_regions: FxHashSet::default(),
|
||||
bound_consts: FxHashSet::default(),
|
||||
};
|
||||
value.visit_with(&mut counter);
|
||||
let bound_tys = counter.bound_tys.len();
|
||||
let bound_regions = if !counter.bound_regions.is_empty() {
|
||||
let mut env = false;
|
||||
let mut anons = FxHashSet::default();
|
||||
let mut named = FxHashSet::default();
|
||||
for br in counter.bound_regions {
|
||||
match br.kind {
|
||||
ty::BrAnon(idx) => {
|
||||
anons.insert(idx);
|
||||
}
|
||||
ty::BrNamed(def_id, _) => {
|
||||
named.insert(def_id);
|
||||
}
|
||||
ty::BrEnv => env = true,
|
||||
}
|
||||
}
|
||||
(if env { 1 } else { 0 }) + anons.len() + named.len()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let bound_consts = counter.bound_consts.len();
|
||||
|
||||
let bound_vars = bound_tys + bound_regions + bound_consts;
|
||||
Binder(value, bound_vars as u32, std::marker::PhantomData)
|
||||
pub fn bind(value: T, tcx: TyCtxt<'tcx>) -> Binder<'tcx, T> {
|
||||
let mut collector = BoundVarsCollector::new();
|
||||
value.visit_with(&mut collector);
|
||||
Binder(value, collector.into_vars(tcx))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> Binder<'tcx, T> {
|
||||
pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
|
||||
Binder(value, vars)
|
||||
}
|
||||
|
||||
/// Skips the binder and returns the "bound" value. This is a
|
||||
/// risky thing to do because it's easy to get confused about
|
||||
/// De Bruijn indices and the like. It is usually better to
|
||||
|
@ -1031,12 +1014,12 @@ impl<'tcx, T> Binder<'tcx, T> {
|
|||
self.0
|
||||
}
|
||||
|
||||
pub fn bound_vars(&self) -> u32 {
|
||||
pub fn bound_vars(&self) -> &'tcx List<BoundVariableKind> {
|
||||
self.1
|
||||
}
|
||||
|
||||
pub fn as_ref(&self) -> Binder<'tcx, &T> {
|
||||
Binder(&self.0, self.1, std::marker::PhantomData)
|
||||
Binder(&self.0, self.1)
|
||||
}
|
||||
|
||||
pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<'tcx, U>
|
||||
|
@ -1050,7 +1033,7 @@ impl<'tcx, T> Binder<'tcx, T> {
|
|||
where
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
Binder(f(self.0), self.1, std::marker::PhantomData)
|
||||
Binder(f(self.0), self.1)
|
||||
}
|
||||
|
||||
/// Wraps a `value` in a binder, using the same bound variables as the
|
||||
|
@ -1063,7 +1046,7 @@ impl<'tcx, T> Binder<'tcx, T> {
|
|||
/// 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<'tcx, U> {
|
||||
Binder(value, self.1, std::marker::PhantomData)
|
||||
Binder(value, self.1)
|
||||
}
|
||||
|
||||
/// Unwraps and returns the value within, but only if it contains
|
||||
|
@ -1094,7 +1077,7 @@ impl<'tcx, T> Binder<'tcx, T> {
|
|||
where
|
||||
F: FnOnce(T, U) -> R,
|
||||
{
|
||||
Binder(f(self.0, u.0), self.1, std::marker::PhantomData)
|
||||
Binder(f(self.0, u.0), self.1)
|
||||
}
|
||||
|
||||
/// Splits the contents into two things that share the same binder
|
||||
|
@ -1108,14 +1091,14 @@ impl<'tcx, T> Binder<'tcx, T> {
|
|||
F: FnOnce(T) -> (U, V),
|
||||
{
|
||||
let (u, v) = f(self.0);
|
||||
(Binder(u, self.1, std::marker::PhantomData), Binder(v, self.1, std::marker::PhantomData))
|
||||
(Binder(u, self.1), Binder(v, self.1))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> Binder<'tcx, Option<T>> {
|
||||
pub fn transpose(self) -> Option<Binder<'tcx, T>> {
|
||||
let bound_vars = self.1;
|
||||
self.0.map(|v| Binder(v, bound_vars, std::marker::PhantomData))
|
||||
self.0.map(|v| Binder(v, bound_vars))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -510,7 +510,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty),
|
||||
ty::ClosureKind::FnOnce => closure_ty,
|
||||
};
|
||||
Some(ty::Binder::bind(env_ty))
|
||||
Some(ty::Binder::bind(env_ty, self))
|
||||
}
|
||||
|
||||
/// Returns `true` if the node pointed to by `def_id` is a `static` item.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue