Skip to content

Commit 063e01b

Browse files
authored
Rollup merge of #144775 - lcnr:skip_binder-comment, r=BoxyUwU
more strongly dissuade use of `skip_binder` People unfortunately encounter `Binder` and `EarlyBinder` very early on when starting out. In these cases its often very easy to use `skip_binder` incorrectly. This makes it more explicit that it should generally not be used and points to the relevant `rustc-dev-guide` chapters. r? `@BoxyUwU`
2 parents d47f8ad + fc46354 commit 063e01b

File tree

1 file changed

+30
-30
lines changed

1 file changed

+30
-30
lines changed

compiler/rustc_type_ir/src/binder.rs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,12 @@ use crate::lift::Lift;
1515
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
1616
use crate::{self as ty, Interner};
1717

18-
/// Binder is a binder for higher-ranked lifetimes or types. It is part of the
18+
/// `Binder` is a binder for higher-ranked lifetimes or types. It is part of the
1919
/// compiler's representation for things like `for<'a> Fn(&'a isize)`
20-
/// (which would be represented by the type `PolyTraitRef ==
21-
/// Binder<I, TraitRef>`). Note that when we instantiate,
22-
/// erase, or otherwise "discharge" these bound vars, we change the
23-
/// type from `Binder<I, T>` to just `T` (see
24-
/// e.g., `liberate_late_bound_regions`).
20+
/// (which would be represented by the type `PolyTraitRef == Binder<I, TraitRef>`).
21+
///
22+
/// See <https://rustc-dev-guide.rust-lang.org/ty_module/instantiating_binders.html>
23+
/// for more details.
2524
///
2625
/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
2726
#[derive_where(Clone; I: Interner, T: Clone)]
@@ -154,22 +153,19 @@ impl<I: Interner, T: TypeVisitable<I>> TypeSuperVisitable<I> for Binder<I, T> {
154153
}
155154

156155
impl<I: Interner, T> Binder<I, T> {
157-
/// Skips the binder and returns the "bound" value. This is a
158-
/// risky thing to do because it's easy to get confused about
159-
/// De Bruijn indices and the like. It is usually better to
160-
/// discharge the binder using `no_bound_vars` or
161-
/// `instantiate_bound_regions` or something like
162-
/// that. `skip_binder` is only valid when you are either
163-
/// extracting data that has nothing to do with bound vars, you
164-
/// are doing some sort of test that does not involve bound
165-
/// regions, or you are being very careful about your depth
166-
/// accounting.
156+
/// Returns the value contained inside of this `for<'a>`. Accessing generic args
157+
/// in the returned value is generally incorrect.
158+
///
159+
/// Please read <https://rustc-dev-guide.rust-lang.org/ty_module/instantiating_binders.html>
160+
/// before using this function. It is usually better to discharge the binder using
161+
/// `no_bound_vars` or `instantiate_bound_regions` or something like that.
167162
///
168-
/// Some examples where `skip_binder` is reasonable:
163+
/// `skip_binder` is only valid when you are either extracting data that does not reference
164+
/// any generic arguments, e.g. a `DefId`, or when you're making sure you only pass the
165+
/// value to things which can handle escaping bound vars.
169166
///
170-
/// - extracting the `DefId` from a PolyTraitRef;
171-
/// - comparing the self type of a PolyTraitRef to see if it is equal to
172-
/// a type parameter `X`, since the type `X` does not reference any regions
167+
/// See existing uses of `.skip_binder()` in `rustc_trait_selection::traits::select`
168+
/// or `rustc_next_trait_solver` for examples.
173169
pub fn skip_binder(self) -> T {
174170
self.value
175171
}
@@ -355,12 +351,11 @@ impl<I: Interner> TypeVisitor<I> for ValidateBoundVars<I> {
355351
}
356352
}
357353

358-
/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)`
354+
/// Similar to [`Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)`
359355
/// needs `T` instantiated immediately. This type primarily exists to avoid forgetting to call
360356
/// `instantiate`.
361357
///
362-
/// If you don't have anything to `instantiate`, you may be looking for
363-
/// [`instantiate_identity`](EarlyBinder::instantiate_identity) or [`skip_binder`](EarlyBinder::skip_binder).
358+
/// See <https://rustc-dev-guide.rust-lang.org/ty_module/early_binder.html> for more details.
364359
#[derive_where(Clone; I: Interner, T: Clone)]
365360
#[derive_where(Copy; I: Interner, T: Copy)]
366361
#[derive_where(PartialEq; I: Interner, T: PartialEq)]
@@ -423,17 +418,22 @@ impl<I: Interner, T> EarlyBinder<I, T> {
423418
EarlyBinder { value, _tcx: PhantomData }
424419
}
425420

426-
/// Skips the binder and returns the "bound" value.
427-
/// This can be used to extract data that does not depend on generic parameters
428-
/// (e.g., getting the `DefId` of the inner value or getting the number of
429-
/// arguments of an `FnSig`). Otherwise, consider using
430-
/// [`instantiate_identity`](EarlyBinder::instantiate_identity).
421+
/// Skips the binder and returns the "bound" value. Accessing generic args
422+
/// in the returned value is generally incorrect.
423+
///
424+
/// Please read <https://rustc-dev-guide.rust-lang.org/ty_module/early_binder.html>
425+
/// before using this function.
426+
///
427+
/// Only use this to extract data that does not depend on generic parameters, e.g.
428+
/// to get the `DefId` of the inner value or the number of arguments ofan `FnSig`,
429+
/// or while making sure to only pass the value to functions which are explicitly
430+
/// set up to handle these uninstantiated generic parameters.
431431
///
432432
/// To skip the binder on `x: &EarlyBinder<I, T>` to obtain `&T`, leverage
433433
/// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`.
434434
///
435-
/// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is
436-
/// the analogous operation on [`super::Binder`].
435+
/// See also [`Binder::skip_binder`](Binder::skip_binder), which is
436+
/// the analogous operation on [`Binder`].
437437
pub fn skip_binder(self) -> T {
438438
self.value
439439
}

0 commit comments

Comments
 (0)