Add var to BoundRegion. Add query to get bound vars for applicable items.
This commit is contained in:
@@ -70,16 +70,16 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionKind {
|
||||
ty::ReEmpty(universe) => {
|
||||
universe.hash_stable(hcx, hasher);
|
||||
}
|
||||
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i) }) => {
|
||||
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => {
|
||||
db.hash_stable(hcx, hasher);
|
||||
i.hash_stable(hcx, hasher);
|
||||
}
|
||||
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name) }) => {
|
||||
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name), .. }) => {
|
||||
db.hash_stable(hcx, hasher);
|
||||
def_id.hash_stable(hcx, hasher);
|
||||
name.hash_stable(hcx, hasher);
|
||||
}
|
||||
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv }) => {
|
||||
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv, .. }) => {
|
||||
db.hash_stable(hcx, hasher);
|
||||
}
|
||||
ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
|
||||
|
||||
@@ -314,7 +314,8 @@ impl<'tcx> CanonicalVarValues<'tcx> {
|
||||
tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
|
||||
}
|
||||
GenericArgKind::Lifetime(..) => {
|
||||
let br = ty::BoundRegion { kind: ty::BrAnon(i) };
|
||||
let br =
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(i), kind: ty::BrAnon(i) };
|
||||
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
|
||||
}
|
||||
GenericArgKind::Const(ct) => tcx
|
||||
|
||||
@@ -83,4 +83,6 @@ pub struct ResolveLifetimes {
|
||||
/// be late-bound if (a) it does NOT appear in a where-clause and
|
||||
/// (b) it DOES appear in the arguments.
|
||||
pub late_bound: FxHashMap<LocalDefId, FxHashSet<ItemLocalId>>,
|
||||
|
||||
pub late_bound_vars: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
|
||||
}
|
||||
|
||||
@@ -1290,6 +1290,10 @@ rustc_queries! {
|
||||
-> Option<Vec<ObjectLifetimeDefault>> {
|
||||
desc { "looking up lifetime defaults for a region on an item" }
|
||||
}
|
||||
query late_bound_vars_map(_: LocalDefId)
|
||||
-> Option<&'tcx FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>> {
|
||||
desc { "looking up late bound vars" }
|
||||
}
|
||||
|
||||
query visibility(def_id: DefId) -> ty::Visibility {
|
||||
eval_always
|
||||
|
||||
@@ -810,7 +810,7 @@ impl CanonicalUserType<'tcx> {
|
||||
ty::ReLateBound(debruijn, br) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(*debruijn, ty::INNERMOST);
|
||||
cvar == br.assert_bound_var()
|
||||
cvar == br.var
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
@@ -2672,6 +2672,17 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn object_lifetime_defaults(self, id: HirId) -> Option<Vec<ObjectLifetimeDefault>> {
|
||||
self.object_lifetime_defaults_map(id.owner)
|
||||
}
|
||||
|
||||
pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
|
||||
self.mk_bound_variable_kinds(
|
||||
self.late_bound_vars_map(id.owner)
|
||||
.and_then(|map| map.get(&id.local_id).cloned())
|
||||
.unwrap_or_else(|| {
|
||||
bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id)
|
||||
})
|
||||
.iter(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl TyCtxtAt<'tcx> {
|
||||
|
||||
@@ -634,6 +634,42 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
.0
|
||||
}
|
||||
|
||||
pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
self.replace_escaping_bound_vars(
|
||||
value,
|
||||
|r| {
|
||||
self.mk_region(ty::ReLateBound(
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion {
|
||||
var: ty::BoundVar::from_usize(r.var.as_usize() + bound_vars),
|
||||
kind: r.kind,
|
||||
},
|
||||
))
|
||||
},
|
||||
|t| {
|
||||
self.mk_ty(ty::Bound(
|
||||
ty::INNERMOST,
|
||||
ty::BoundTy {
|
||||
var: ty::BoundVar::from_usize(t.var.as_usize() + bound_vars),
|
||||
kind: t.kind,
|
||||
},
|
||||
))
|
||||
},
|
||||
|c, ty| {
|
||||
self.mk_const(ty::Const {
|
||||
val: ty::ConstKind::Bound(
|
||||
ty::INNERMOST,
|
||||
ty::BoundVar::from_usize(c.as_usize() + bound_vars),
|
||||
),
|
||||
ty,
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a set of all late-bound regions that are constrained
|
||||
/// by `value`, meaning that if we instantiate those LBR with
|
||||
/// variables and equate `value` with something else, those
|
||||
@@ -695,16 +731,21 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
let mut counter = 0;
|
||||
Binder::bind(
|
||||
self.replace_late_bound_regions(sig, |_| {
|
||||
let br = ty::BoundRegion { kind: ty::BrAnon(counter) };
|
||||
let inner = self
|
||||
.replace_late_bound_regions(sig, |_| {
|
||||
let br = ty::BoundRegion {
|
||||
var: ty::BoundVar::from_u32(counter),
|
||||
kind: ty::BrAnon(counter),
|
||||
};
|
||||
let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br));
|
||||
counter += 1;
|
||||
r
|
||||
})
|
||||
.0,
|
||||
self,
|
||||
)
|
||||
.0;
|
||||
let bound_vars = self.mk_bound_variable_kinds(
|
||||
(0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))),
|
||||
);
|
||||
Binder::bind_with_vars(inner, bound_vars)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -777,27 +818,105 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
|
||||
}
|
||||
|
||||
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::ReLateBound(index, _br) if *index == self.binder_index => {
|
||||
bug!("{:?} {:?}", index, _br)
|
||||
}
|
||||
|
||||
ty::BrAnon(var) => match self.vars.entry(var) {
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(ty::BoundVariableKind::Region(br.kind));
|
||||
_ => (),
|
||||
};
|
||||
|
||||
r.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ValidateBoundVars<'tcx> {
|
||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||
binder_index: ty::DebruijnIndex,
|
||||
// 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> ValidateBoundVars<'tcx> {
|
||||
pub fn new(bound_vars: &'tcx ty::List<ty::BoundVariableKind>) -> Self {
|
||||
ValidateBoundVars {
|
||||
bound_vars,
|
||||
binder_index: ty::INNERMOST,
|
||||
visited: SsoHashSet::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'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::BREAK;
|
||||
}
|
||||
match *t.kind() {
|
||||
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
|
||||
if self.bound_vars.len() <= bound_ty.var.as_usize() {
|
||||
panic!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars);
|
||||
}
|
||||
let list_var = self.bound_vars[bound_ty.var.as_usize()];
|
||||
match list_var {
|
||||
ty::BoundVariableKind::Ty(kind) => {
|
||||
if kind != bound_ty.kind {
|
||||
panic!(
|
||||
"Mismatched type kinds: {:?} doesn't var in list {:?}",
|
||||
bound_ty.kind, list_var
|
||||
);
|
||||
}
|
||||
}
|
||||
Entry::Occupied(entry) => match entry.get() {
|
||||
ty::BoundVariableKind::Region(_) => {}
|
||||
_ => bug!("Conflicting bound vars"),
|
||||
},
|
||||
},
|
||||
|
||||
ty::BrEnv => {
|
||||
// FIXME
|
||||
_ => panic!(
|
||||
"Mismatched bound variable kinds! Expected type, found {:?}",
|
||||
list_var
|
||||
),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match r {
|
||||
ty::ReLateBound(index, br) if *index == self.binder_index => {
|
||||
if self.bound_vars.len() <= br.var.as_usize() {
|
||||
panic!("Not enough bound vars: {:?} not found in {:?}", *br, self.bound_vars);
|
||||
}
|
||||
let list_var = self.bound_vars[br.var.as_usize()];
|
||||
match list_var {
|
||||
ty::BoundVariableKind::Region(kind) => {
|
||||
if kind != br.kind {
|
||||
panic!(
|
||||
"Mismatched region kinds: {:?} doesn't match var ({:?}) in list ({:?})",
|
||||
br.kind, list_var, self.bound_vars
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => panic!(
|
||||
"Mismatched bound variable kinds! Expected region, found {:?}",
|
||||
list_var
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// ignore-tidy-filelength
|
||||
use crate::ich::StableHashingContext;
|
||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
|
||||
@@ -2481,21 +2482,42 @@ impl<'tcx> ty::Instance<'tcx> {
|
||||
ty::Closure(def_id, substs) => {
|
||||
let sig = substs.as_closure().sig();
|
||||
|
||||
let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
|
||||
sig.map_bound(|sig| {
|
||||
let bound_vars = tcx.mk_bound_variable_kinds(
|
||||
sig.bound_vars()
|
||||
.iter()
|
||||
.chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
|
||||
);
|
||||
let br = ty::BoundRegion {
|
||||
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
|
||||
kind: ty::BoundRegionKind::BrEnv,
|
||||
};
|
||||
let env_region = ty::ReLateBound(ty::INNERMOST, br);
|
||||
let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
|
||||
|
||||
let sig = sig.skip_binder();
|
||||
ty::Binder::bind_with_vars(
|
||||
tcx.mk_fn_sig(
|
||||
iter::once(env_ty.skip_binder()).chain(sig.inputs().iter().cloned()),
|
||||
iter::once(env_ty).chain(sig.inputs().iter().cloned()),
|
||||
sig.output(),
|
||||
sig.c_variadic,
|
||||
sig.unsafety,
|
||||
sig.abi,
|
||||
)
|
||||
})
|
||||
),
|
||||
bound_vars,
|
||||
)
|
||||
}
|
||||
ty::Generator(_, substs, _) => {
|
||||
let sig = substs.as_generator().poly_sig();
|
||||
|
||||
let br = ty::BoundRegion { kind: ty::BrEnv };
|
||||
let bound_vars = tcx.mk_bound_variable_kinds(
|
||||
sig.bound_vars()
|
||||
.iter()
|
||||
.chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
|
||||
);
|
||||
let br = ty::BoundRegion {
|
||||
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
|
||||
kind: ty::BoundRegionKind::BrEnv,
|
||||
};
|
||||
let env_region = ty::ReLateBound(ty::INNERMOST, br);
|
||||
let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
|
||||
|
||||
@@ -2504,21 +2526,21 @@ impl<'tcx> ty::Instance<'tcx> {
|
||||
let pin_substs = tcx.intern_substs(&[env_ty.into()]);
|
||||
let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
|
||||
|
||||
sig.map_bound(|sig| {
|
||||
let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
|
||||
let state_adt_ref = tcx.adt_def(state_did);
|
||||
let state_substs =
|
||||
tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
|
||||
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
|
||||
|
||||
let sig = sig.skip_binder();
|
||||
let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
|
||||
let state_adt_ref = tcx.adt_def(state_did);
|
||||
let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
|
||||
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
|
||||
ty::Binder::bind_with_vars(
|
||||
tcx.mk_fn_sig(
|
||||
[env_ty, sig.resume_ty].iter(),
|
||||
&ret_ty,
|
||||
false,
|
||||
hir::Unsafety::Normal,
|
||||
rustc_target::spec::abi::Abi::Rust,
|
||||
)
|
||||
})
|
||||
),
|
||||
bound_vars,
|
||||
)
|
||||
}
|
||||
_ => bug!("unexpected type {:?} in Instance::fn_sig", ty),
|
||||
}
|
||||
|
||||
@@ -543,10 +543,33 @@ impl<'tcx> Predicate<'tcx> {
|
||||
// substitution code expects equal binding levels in the values
|
||||
// from the substitution and the value being substituted into, and
|
||||
// this trick achieves that).
|
||||
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))
|
||||
|
||||
// Working through the second example:
|
||||
// trait_ref: for<'x> T: Foo1<'^0.0>; substs: [T, '^0.0]
|
||||
// predicate: for<'b> Self: Bar1<'a, '^0.0>; substs: [Self, 'a, '^0.0]
|
||||
// We want to end up with:
|
||||
// for<'x, 'b> T: Bar1<'^0.0, '^0.1>
|
||||
// To do this:
|
||||
// 1) We must shift all bound vars in predicate by the length
|
||||
// of trait ref's bound vars. So, we would end up with predicate like
|
||||
// Self: Bar1<'a, '^0.1>
|
||||
// 2) We can then apply the trait substs to this, ending up with
|
||||
// T: Bar1<'^0.0, '^0.1>
|
||||
// 3) Finally, to create the final bound vars, we concatenate the bound
|
||||
// vars of the trait ref with those of the predicate:
|
||||
// ['x, 'b]
|
||||
let bound_pred = self.kind();
|
||||
let pred_bound_vars = bound_pred.bound_vars();
|
||||
let trait_bound_vars = trait_ref.bound_vars();
|
||||
// 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1>
|
||||
let shifted_pred =
|
||||
tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
|
||||
// 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
|
||||
let new = shifted_pred.subst(tcx, trait_ref.skip_binder().substs);
|
||||
// 3) ['x] + ['b] -> ['x, 'b]
|
||||
let bound_vars =
|
||||
tcx.mk_bound_variable_kinds(trait_bound_vars.iter().chain(pred_bound_vars));
|
||||
tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1636,7 +1636,7 @@ impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
|
||||
data.name != kw::Empty && data.name != kw::UnderscoreLifetime
|
||||
}
|
||||
|
||||
ty::ReLateBound(_, ty::BoundRegion { kind: br })
|
||||
ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
|
||||
| ty::ReFree(ty::FreeRegion { bound_region: br, .. })
|
||||
| ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
|
||||
if let ty::BrNamed(_, name) = br {
|
||||
@@ -1715,7 +1715,7 @@ impl<F: fmt::Write> FmtPrinter<'_, '_, F> {
|
||||
return Ok(self);
|
||||
}
|
||||
}
|
||||
ty::ReLateBound(_, ty::BoundRegion { kind: br })
|
||||
ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
|
||||
| ty::ReFree(ty::FreeRegion { bound_region: br, .. })
|
||||
| ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
|
||||
if let ty::BrNamed(_, name) = br {
|
||||
@@ -1821,7 +1821,8 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
|
||||
ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
|
||||
}
|
||||
};
|
||||
self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind }))
|
||||
self.tcx
|
||||
.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
|
||||
});
|
||||
start_or_continue(&mut self, "", "> ")?;
|
||||
|
||||
@@ -1865,7 +1866,7 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
|
||||
struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet<Symbol>);
|
||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> {
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name) }) = *r {
|
||||
if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
|
||||
self.0.insert(name);
|
||||
}
|
||||
r.super_visit_with(self)
|
||||
|
||||
@@ -6,6 +6,7 @@ use self::TyKind::*;
|
||||
|
||||
use crate::infer::canonical::Canonical;
|
||||
use crate::ty::fold::BoundVarsCollector;
|
||||
use crate::ty::fold::ValidateBoundVars;
|
||||
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
|
||||
use crate::ty::InferTy::{self, *};
|
||||
use crate::ty::{
|
||||
@@ -63,22 +64,10 @@ pub enum BoundRegionKind {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)]
|
||||
#[derive(HashStable)]
|
||||
pub struct BoundRegion {
|
||||
pub var: BoundVar,
|
||||
pub kind: BoundRegionKind,
|
||||
}
|
||||
|
||||
impl BoundRegion {
|
||||
/// When canonicalizing, we replace unbound inference variables and free
|
||||
/// regions with anonymous late bound regions. This method asserts that
|
||||
/// we have an anonymous late bound region, which hence may refer to
|
||||
/// a canonical variable.
|
||||
pub fn assert_bound_var(&self) -> BoundVar {
|
||||
match self.kind {
|
||||
BoundRegionKind::BrAnon(var) => BoundVar::from_u32(var),
|
||||
_ => bug!("bound region is not anonymous"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BoundRegionKind {
|
||||
pub fn is_named(&self) -> bool {
|
||||
match *self {
|
||||
@@ -987,13 +976,17 @@ where
|
||||
value.visit_with(&mut collector);
|
||||
Binder(value, collector.into_vars(tcx))
|
||||
}
|
||||
|
||||
pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
|
||||
if cfg!(debug_assertions) {
|
||||
let mut validator = ValidateBoundVars::new(vars);
|
||||
value.visit_with(&mut validator);
|
||||
}
|
||||
Binder(value, vars)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -1022,18 +1015,31 @@ impl<'tcx, T> Binder<'tcx, T> {
|
||||
Binder(&self.0, self.1)
|
||||
}
|
||||
|
||||
pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<'tcx, U>
|
||||
pub fn map_bound_ref_unchecked<F, U>(&self, f: F) -> Binder<'tcx, U>
|
||||
where
|
||||
F: FnOnce(&T) -> U,
|
||||
{
|
||||
let value = f(&self.0);
|
||||
Binder(value, self.1)
|
||||
}
|
||||
|
||||
pub fn map_bound_ref<F, U: TypeFoldable<'tcx>>(&self, f: F) -> Binder<'tcx, U>
|
||||
where
|
||||
F: FnOnce(&T) -> U,
|
||||
{
|
||||
self.as_ref().map_bound(f)
|
||||
}
|
||||
|
||||
pub fn map_bound<F, U>(self, f: F) -> Binder<'tcx, U>
|
||||
pub fn map_bound<F, U: TypeFoldable<'tcx>>(self, f: F) -> Binder<'tcx, U>
|
||||
where
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
Binder(f(self.0), self.1)
|
||||
let value = f(self.0);
|
||||
if cfg!(debug_assertions) {
|
||||
let mut validator = ValidateBoundVars::new(self.1);
|
||||
value.visit_with(&mut validator);
|
||||
}
|
||||
Binder(value, self.1)
|
||||
}
|
||||
|
||||
/// Wraps a `value` in a binder, using the same bound variables as the
|
||||
@@ -1045,7 +1051,14 @@ impl<'tcx, T> Binder<'tcx, T> {
|
||||
/// 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<'tcx, U> {
|
||||
pub fn rebind<U>(&self, value: U) -> Binder<'tcx, U>
|
||||
where
|
||||
U: TypeFoldable<'tcx>,
|
||||
{
|
||||
if cfg!(debug_assertions) {
|
||||
let mut validator = ValidateBoundVars::new(self.bound_vars());
|
||||
value.visit_with(&mut validator);
|
||||
}
|
||||
Binder(value, self.1)
|
||||
}
|
||||
|
||||
@@ -1066,20 +1079,6 @@ impl<'tcx, T> Binder<'tcx, T> {
|
||||
if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
|
||||
}
|
||||
|
||||
/// Given two things that have the same binder level,
|
||||
/// and an operation that wraps on their contents, executes the operation
|
||||
/// and then wraps its result.
|
||||
///
|
||||
/// `f` should consider bound regions at depth 1 to be free, and
|
||||
/// anything it produces with bound regions at depth 1 will be
|
||||
/// bound in the resulting return value.
|
||||
pub fn fuse<U, F, R>(self, u: Binder<'tcx, U>, f: F) -> Binder<'tcx, R>
|
||||
where
|
||||
F: FnOnce(T, U) -> R,
|
||||
{
|
||||
Binder(f(self.0, u.0), self.1)
|
||||
}
|
||||
|
||||
/// Splits the contents into two things that share the same binder
|
||||
/// level as the original, returning two distinct binders.
|
||||
///
|
||||
@@ -1204,7 +1203,7 @@ pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>;
|
||||
impl<'tcx> PolyFnSig<'tcx> {
|
||||
#[inline]
|
||||
pub fn inputs(&self) -> Binder<'tcx, &'tcx [Ty<'tcx>]> {
|
||||
self.map_bound_ref(|fn_sig| fn_sig.inputs())
|
||||
self.map_bound_ref_unchecked(|fn_sig| fn_sig.inputs())
|
||||
}
|
||||
#[inline]
|
||||
pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> {
|
||||
|
||||
@@ -499,18 +499,18 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
self,
|
||||
closure_def_id: DefId,
|
||||
closure_substs: SubstsRef<'tcx>,
|
||||
) -> Option<ty::Binder<'tcx, Ty<'tcx>>> {
|
||||
env_region: ty::RegionKind,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
let closure_ty = self.mk_closure(closure_def_id, closure_substs);
|
||||
let br = ty::BoundRegion { kind: ty::BrEnv };
|
||||
let env_region = ty::ReLateBound(ty::INNERMOST, br);
|
||||
let closure_kind_ty = closure_substs.as_closure().kind_ty();
|
||||
let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
|
||||
debug_assert!(!closure_ty.has_escaping_bound_vars());
|
||||
let env_ty = match closure_kind {
|
||||
ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty),
|
||||
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, self))
|
||||
Some(env_ty)
|
||||
}
|
||||
|
||||
/// Returns `true` if the node pointed to by `def_id` is a `static` item.
|
||||
|
||||
Reference in New Issue
Block a user