change binders from tuple structs to named fields

This commit is contained in:
lcnr 2023-06-19 11:38:07 +02:00
parent 8d1fa473dd
commit f2975810a5
2 changed files with 60 additions and 55 deletions

View File

@ -1007,7 +1007,10 @@ pub fn expect_const(self) {
/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(HashStable, Lift)]
pub struct Binder<'tcx, T>(T, &'tcx List<BoundVariableKind>);
pub struct Binder<'tcx, T> {
value: T,
bound_vars: &'tcx List<BoundVariableKind>,
}
impl<'tcx, T> Binder<'tcx, T>
where
@ -1023,15 +1026,15 @@ pub fn dummy(value: T) -> Binder<'tcx, T> {
!value.has_escaping_bound_vars(),
"`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder."
);
Binder(value, ty::List::empty())
Binder { value, bound_vars: ty::List::empty() }
}
pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
pub fn bind_with_vars(value: T, bound_vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
if cfg!(debug_assertions) {
let mut validator = ValidateBoundVars::new(vars);
let mut validator = ValidateBoundVars::new(bound_vars);
value.visit_with(&mut validator);
}
Binder(value, vars)
Binder { value, bound_vars }
}
}
@ -1053,30 +1056,30 @@ impl<'tcx, T> Binder<'tcx, T> {
/// - comparing the self type of a PolyTraitRef to see if it is equal to
/// a type parameter `X`, since the type `X` does not reference any regions
pub fn skip_binder(self) -> T {
self.0
self.value
}
pub fn bound_vars(&self) -> &'tcx List<BoundVariableKind> {
self.1
self.bound_vars
}
pub fn as_ref(&self) -> Binder<'tcx, &T> {
Binder(&self.0, self.1)
Binder { value: &self.value, bound_vars: self.bound_vars }
}
pub fn as_deref(&self) -> Binder<'tcx, &T::Target>
where
T: Deref,
{
Binder(&self.0, self.1)
Binder { value: &self.value, bound_vars: self.bound_vars }
}
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)
let value = f(&self.value);
Binder { value, bound_vars: self.bound_vars }
}
pub fn map_bound_ref<F, U: TypeVisitable<TyCtxt<'tcx>>>(&self, f: F) -> Binder<'tcx, U>
@ -1090,12 +1093,13 @@ pub fn map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>>(self, f: F) -> Binder<'tcx,
where
F: FnOnce(T) -> U,
{
let value = f(self.0);
let Binder { value, bound_vars } = self;
let value = f(value);
if cfg!(debug_assertions) {
let mut validator = ValidateBoundVars::new(self.1);
let mut validator = ValidateBoundVars::new(bound_vars);
value.visit_with(&mut validator);
}
Binder(value, self.1)
Binder { value, bound_vars }
}
pub fn try_map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>, E>(
@ -1105,12 +1109,13 @@ pub fn try_map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>, E>(
where
F: FnOnce(T) -> Result<U, E>,
{
let value = f(self.0)?;
let Binder { value, bound_vars } = self;
let value = f(value)?;
if cfg!(debug_assertions) {
let mut validator = ValidateBoundVars::new(self.1);
let mut validator = ValidateBoundVars::new(bound_vars);
value.visit_with(&mut validator);
}
Ok(Binder(value, self.1))
Ok(Binder { value, bound_vars })
}
/// Wraps a `value` in a binder, using the same bound variables as the
@ -1126,11 +1131,7 @@ pub fn rebind<U>(&self, value: U) -> Binder<'tcx, U>
where
U: TypeVisitable<TyCtxt<'tcx>>,
{
if cfg!(debug_assertions) {
let mut validator = ValidateBoundVars::new(self.bound_vars());
value.visit_with(&mut validator);
}
Binder(value, self.1)
Binder::bind_with_vars(value, self.bound_vars)
}
/// Unwraps and returns the value within, but only if it contains
@ -1147,7 +1148,7 @@ pub fn no_bound_vars(self) -> Option<T>
where
T: TypeVisitable<TyCtxt<'tcx>>,
{
if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
}
/// Splits the contents into two things that share the same binder
@ -1160,22 +1161,23 @@ pub fn split<U, V, F>(self, f: F) -> (Binder<'tcx, U>, Binder<'tcx, V>)
where
F: FnOnce(T) -> (U, V),
{
let (u, v) = f(self.0);
(Binder(u, self.1), Binder(v, self.1))
let Binder { value, bound_vars } = self;
let (u, v) = f(value);
(Binder { value: u, bound_vars }, Binder { value: v, bound_vars })
}
}
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))
let Binder { value, bound_vars } = self;
value.map(|value| Binder { value, bound_vars })
}
}
impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> {
let bound_vars = self.1;
self.0.into_iter().map(|v| Binder(v, bound_vars))
let Binder { value, bound_vars } = self;
value.into_iter().map(|value| Binder { value, bound_vars })
}
}
@ -1184,7 +1186,7 @@ impl<'tcx, T> IntoDiagnosticArg for Binder<'tcx, T>
T: IntoDiagnosticArg,
{
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
self.0.into_diagnostic_arg()
self.value.into_diagnostic_arg()
}
}

View File

@ -538,19 +538,21 @@ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFl
/// [`subst_identity`](EarlyBinder::subst_identity) or [`skip_binder`](EarlyBinder::skip_binder).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(Encodable, Decodable, HashStable)]
pub struct EarlyBinder<T>(T);
pub struct EarlyBinder<T> {
value: T,
}
/// For early binders, you should first call `subst` before using any visitors.
impl<'tcx, T> !TypeFoldable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
impl<'tcx, T> !TypeVisitable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
impl<T> EarlyBinder<T> {
pub fn bind(inner: T) -> EarlyBinder<T> {
EarlyBinder(inner)
pub fn bind(value: T) -> EarlyBinder<T> {
EarlyBinder { value }
}
pub fn as_ref(&self) -> EarlyBinder<&T> {
EarlyBinder(&self.0)
EarlyBinder { value: &self.value }
}
pub fn map_bound_ref<F, U>(&self, f: F) -> EarlyBinder<U>
@ -564,20 +566,20 @@ pub fn map_bound<F, U>(self, f: F) -> EarlyBinder<U>
where
F: FnOnce(T) -> U,
{
let value = f(self.0);
EarlyBinder(value)
let value = f(self.value);
EarlyBinder { value }
}
pub fn try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E>
where
F: FnOnce(T) -> Result<U, E>,
{
let value = f(self.0)?;
Ok(EarlyBinder(value))
let value = f(self.value)?;
Ok(EarlyBinder { value })
}
pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
EarlyBinder(value)
EarlyBinder { value }
}
/// Skips the binder and returns the "bound" value.
@ -592,19 +594,20 @@ pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
/// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is
/// the analogous operation on [`super::Binder`].
pub fn skip_binder(self) -> T {
self.0
self.value
}
}
impl<T> EarlyBinder<Option<T>> {
pub fn transpose(self) -> Option<EarlyBinder<T>> {
self.0.map(|v| EarlyBinder(v))
self.value.map(|value| EarlyBinder { value })
}
}
impl<T, U> EarlyBinder<(T, U)> {
pub fn transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>) {
(EarlyBinder(self.0.0), EarlyBinder(self.0.1))
let EarlyBinder { value: (lhs, rhs) } = self;
(EarlyBinder { value: lhs }, EarlyBinder { value: rhs })
}
}
@ -617,13 +620,13 @@ pub fn subst_iter(
tcx: TyCtxt<'tcx>,
substs: &'s [GenericArg<'tcx>],
) -> SubstIter<'s, 'tcx, I> {
SubstIter { it: self.0.into_iter(), tcx, substs }
SubstIter { it: self.value.into_iter(), tcx, substs }
}
/// Similar to [`subst_identity`](EarlyBinder::subst_identity),
/// but on an iterator of `TypeFoldable` values.
pub fn subst_identity_iter(self) -> I::IntoIter {
self.0.into_iter()
self.value.into_iter()
}
}
@ -640,7 +643,7 @@ impl<'tcx, I: IntoIterator> Iterator for SubstIter<'_, 'tcx, I>
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
Some(EarlyBinder(self.it.next()?).subst(self.tcx, self.substs))
Some(EarlyBinder { value: self.it.next()? }.subst(self.tcx, self.substs))
}
fn size_hint(&self) -> (usize, Option<usize>) {
@ -654,7 +657,7 @@ impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIter<'_, 'tcx, I>
I::Item: TypeFoldable<TyCtxt<'tcx>>,
{
fn next_back(&mut self) -> Option<Self::Item> {
Some(EarlyBinder(self.it.next_back()?).subst(self.tcx, self.substs))
Some(EarlyBinder { value: self.it.next_back()? }.subst(self.tcx, self.substs))
}
}
@ -675,13 +678,13 @@ pub fn subst_iter_copied(
tcx: TyCtxt<'tcx>,
substs: &'s [GenericArg<'tcx>],
) -> SubstIterCopied<'s, 'tcx, I> {
SubstIterCopied { it: self.0.into_iter(), tcx, substs }
SubstIterCopied { it: self.value.into_iter(), tcx, substs }
}
/// Similar to [`subst_identity`](EarlyBinder::subst_identity),
/// but on an iterator of values that deref to a `TypeFoldable`.
pub fn subst_identity_iter_copied(self) -> impl Iterator<Item = <I::Item as Deref>::Target> {
self.0.into_iter().map(|v| *v)
self.value.into_iter().map(|v| *v)
}
}
@ -699,7 +702,7 @@ impl<'tcx, I: IntoIterator> Iterator for SubstIterCopied<'_, 'tcx, I>
type Item = <I::Item as Deref>::Target;
fn next(&mut self) -> Option<Self::Item> {
Some(EarlyBinder(*self.it.next()?).subst(self.tcx, self.substs))
self.it.next().map(|value| EarlyBinder { value: *value }.subst(self.tcx, self.substs))
}
fn size_hint(&self) -> (usize, Option<usize>) {
@ -714,7 +717,7 @@ impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIterCopied<'_, 'tcx, I>
<I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
{
fn next_back(&mut self) -> Option<Self::Item> {
Some(EarlyBinder(*self.it.next_back()?).subst(self.tcx, self.substs))
self.it.next_back().map(|value| EarlyBinder { value: *value }.subst(self.tcx, self.substs))
}
}
@ -732,7 +735,7 @@ pub struct EarlyBinderIter<T> {
impl<T: IntoIterator> EarlyBinder<T> {
pub fn transpose_iter(self) -> EarlyBinderIter<T::IntoIter> {
EarlyBinderIter { t: self.0.into_iter() }
EarlyBinderIter { t: self.value.into_iter() }
}
}
@ -740,7 +743,7 @@ impl<T: Iterator> Iterator for EarlyBinderIter<T> {
type Item = EarlyBinder<T::Item>;
fn next(&mut self) -> Option<Self::Item> {
self.t.next().map(|i| EarlyBinder(i))
self.t.next().map(|value| EarlyBinder { value })
}
fn size_hint(&self) -> (usize, Option<usize>) {
@ -751,7 +754,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> ty::EarlyBinder<T> {
pub fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> T {
let mut folder = SubstFolder { tcx, substs, binders_passed: 0 };
self.0.fold_with(&mut folder)
self.value.fold_with(&mut folder)
}
/// Makes the identity substitution `T0 => T0, ..., TN => TN`.
@ -763,12 +766,12 @@ pub fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> T {
/// - Inside of the body of `foo`, we treat `T` as a placeholder by calling
/// `subst_identity` to discharge the `EarlyBinder`.
pub fn subst_identity(self) -> T {
self.0
self.value
}
/// Returns the inner value, but only if it contains no bound vars.
pub fn no_bound_vars(self) -> Option<T> {
if !self.0.has_param() { Some(self.0) } else { None }
if !self.value.has_param() { Some(self.value) } else { None }
}
}