-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Description
Part of #49810.
The Binder
type is used to represent higher-ranked regions:
Lines 645 to 653 in 4b9b70c
/// Binder is a binder for higher-ranked lifetimes. It is part of the | |
/// compiler's representation for things like `for<'a> Fn(&'a isize)` | |
/// (which would be represented by the type `PolyTraitRef == | |
/// Binder<TraitRef>`). Note that when we skolemize, instantiate, | |
/// erase, or otherwise "discharge" these bound regions, we change the | |
/// type from `Binder<T>` to just `T` (see | |
/// e.g. `liberate_late_bound_regions`). | |
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] | |
pub struct Binder<T>(pub T); |
I have long wanted to make that field private and thus to force users of Binder
to go through the more "high-level" methods (as an aside, it might be nice to move binder to its own module too, so that ty
can't use its private fields).
Right now, when we do ty::Binder(value)
, that means that any things with a debruijn-index of 1 (soon to be zero) in value
will be bound by this binder. Maybe we can add a ty::Binder::bind(value)
for this.
On the other hand, there are times when we do not expect value
to have any bound regions in it -- for those cases we often use ty::Binder(value)
today, but it'd be better if used ty::Binder::dummy(value)
, which adds an assertion.
Similarly, any attempt to directly access the "bound" value (binder.0
) is better written with binder.skip_binder()
, which makes it more clear what's happening. Better yet is to add an accessor, somewhat like the def_id
function defined on Binder<TraitRef<'tcx>>
. This is currently written to access the field 0
directly, which is bad, but the good part is that it is "safe" to do, because DefId
is a type that never contains a bound name:
Lines 573 to 575 in 4b9b70c
pub fn def_id(&self) -> DefId { | |
self.0.def_id | |
} |
Note that accessing fields which may have bound names should ideally preserve the binding level, like the inputs
function on Binder<FnSig<'tcx>>
:
Lines 841 to 843 in 4b9b70c
pub fn inputs(&self) -> Binder<&'tcx [Ty<'tcx>]> { | |
Binder(self.skip_binder().inputs()) | |
} |
This is saying, given a function like for<'a> fn(&'a u32) -> &'a u32
, we get back a list of input types like for<'a> [&'a u32]
. Note that the binder is preserved. (Internally, though, it could be rewritten to use the helper Binder::map_bound
:
Lines 697 to 701 in 4b9b70c
pub fn map_bound<F, U>(self, f: F) -> Binder<U> | |
where F: FnOnce(T) -> U | |
{ | |
ty::Binder(f(self.0)) | |
} |