Add var to BoundRegion. Add query to get bound vars for applicable items.
This commit is contained in:
@@ -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>> {
|
||||
|
||||
Reference in New Issue
Block a user