fix most compiler/ doctests
This commit is contained in:
parent
bf611439e3
commit
7907385999
116 changed files with 666 additions and 609 deletions
|
@ -742,7 +742,7 @@ impl<'hir> Map<'hir> {
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,E0308
|
||||
/// fn foo(x: usize) -> bool {
|
||||
/// loop {
|
||||
/// true // If `get_return_block` gets passed the `id` corresponding
|
||||
|
|
|
@ -10,7 +10,7 @@ use rustc_span::Span;
|
|||
/// Requires that `region` must be equal to one of the regions in `choice_regions`.
|
||||
/// We often denote this using the syntax:
|
||||
///
|
||||
/// ```
|
||||
/// ```text
|
||||
/// R0 member of [O1..On]
|
||||
/// ```
|
||||
#[derive(Debug, Clone, HashStable, TypeFoldable, Lift)]
|
||||
|
|
|
@ -770,11 +770,11 @@ impl InitMask {
|
|||
///
|
||||
/// Note that all examples below are written with 8 (instead of 64) bit blocks for simplicity,
|
||||
/// and with the least significant bit (and lowest block) first:
|
||||
///
|
||||
/// 00000000|00000000
|
||||
/// ^ ^ ^ ^
|
||||
/// index: 0 7 8 15
|
||||
///
|
||||
/// ```text
|
||||
/// 00000000|00000000
|
||||
/// ^ ^ ^ ^
|
||||
/// index: 0 7 8 15
|
||||
/// ```
|
||||
/// Also, if not stated, assume that `is_init = true`, that is, we are searching for the first 1 bit.
|
||||
fn find_bit_fast(
|
||||
init_mask: &InitMask,
|
||||
|
|
|
@ -737,14 +737,14 @@ pub enum BorrowKind {
|
|||
/// This is used when lowering matches: when matching on a place we want to
|
||||
/// ensure that place have the same value from the start of the match until
|
||||
/// an arm is selected. This prevents this code from compiling:
|
||||
///
|
||||
/// let mut x = &Some(0);
|
||||
/// match *x {
|
||||
/// None => (),
|
||||
/// Some(_) if { x = &None; false } => (),
|
||||
/// Some(_) => (),
|
||||
/// }
|
||||
///
|
||||
/// ```compile_fail,E0510
|
||||
/// let mut x = &Some(0);
|
||||
/// match *x {
|
||||
/// None => (),
|
||||
/// Some(_) if { x = &None; false } => (),
|
||||
/// Some(_) => (),
|
||||
/// }
|
||||
/// ```
|
||||
/// This can't be a shared borrow because mutably borrowing (*x as Some).0
|
||||
/// should not prevent `if let None = x { ... }`, for example, because the
|
||||
/// mutating `(*x as Some).0` can't affect the discriminant of `x`.
|
||||
|
@ -755,27 +755,30 @@ pub enum BorrowKind {
|
|||
/// cannot currently be expressed by the user and is used only in
|
||||
/// implicit closure bindings. It is needed when the closure is
|
||||
/// borrowing or mutating a mutable referent, e.g.:
|
||||
///
|
||||
/// let x: &mut isize = ...;
|
||||
/// let y = || *x += 5;
|
||||
///
|
||||
/// ```
|
||||
/// let mut z = 3;
|
||||
/// let x: &mut isize = &mut z;
|
||||
/// let y = || *x += 5;
|
||||
/// ```
|
||||
/// If we were to try to translate this closure into a more explicit
|
||||
/// form, we'd encounter an error with the code as written:
|
||||
///
|
||||
/// struct Env { x: & &mut isize }
|
||||
/// let x: &mut isize = ...;
|
||||
/// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
|
||||
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
|
||||
///
|
||||
/// ```compile_fail,E0594
|
||||
/// struct Env<'a> { x: &'a &'a mut isize }
|
||||
/// let mut z = 3;
|
||||
/// let x: &mut isize = &mut z;
|
||||
/// let y = (&mut Env { x: &x }, fn_ptr); // Closure is pair of env and fn
|
||||
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
|
||||
/// ```
|
||||
/// This is then illegal because you cannot mutate an `&mut` found
|
||||
/// in an aliasable location. To solve, you'd have to translate with
|
||||
/// an `&mut` borrow:
|
||||
///
|
||||
/// struct Env { x: &mut &mut isize }
|
||||
/// let x: &mut isize = ...;
|
||||
/// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
|
||||
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
|
||||
///
|
||||
/// ```compile_fail,E0596
|
||||
/// struct Env<'a> { x: &'a mut &'a mut isize }
|
||||
/// let mut z = 3;
|
||||
/// let x: &mut isize = &mut z;
|
||||
/// let y = (&mut Env { x: &mut x }, fn_ptr); // changed from &x to &mut x
|
||||
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
|
||||
/// ```
|
||||
/// Now the assignment to `**env.x` is legal, but creating a
|
||||
/// mutable pointer to `x` is not because `x` is not mutable. We
|
||||
/// could fix this by declaring `x` as `let mut x`. This is ok in
|
||||
|
@ -1016,7 +1019,7 @@ pub struct LocalDecl<'tcx> {
|
|||
/// ```
|
||||
/// fn foo(x: &str) {
|
||||
/// match {
|
||||
/// match x.parse().unwrap() {
|
||||
/// match x.parse::<u32>().unwrap() {
|
||||
/// y => y + 2
|
||||
/// }
|
||||
/// } {
|
||||
|
@ -1690,9 +1693,9 @@ pub enum StatementKind<'tcx> {
|
|||
|
||||
/// Encodes a user's type ascription. These need to be preserved
|
||||
/// intact so that NLL can respect them. For example:
|
||||
///
|
||||
/// let a: T = y;
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// let a: T = y;
|
||||
/// ```
|
||||
/// The effect of this annotation is to relate the type `T_y` of the place `y`
|
||||
/// to the user-given type `T`. The effect depends on the specified variance:
|
||||
///
|
||||
|
@ -1985,7 +1988,7 @@ pub enum ProjectionElem<V, T> {
|
|||
/// These indices are generated by slice patterns. Easiest to explain
|
||||
/// by example:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false },
|
||||
/// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false },
|
||||
/// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true },
|
||||
|
@ -3179,7 +3182,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
///
|
||||
/// An example:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// struct S<'a>((i32, &'a str), String);
|
||||
/// let S((_, w): (i32, &'static str), _): S = ...;
|
||||
/// // ------ ^^^^^^^^^^^^^^^^^^^ (1)
|
||||
|
|
|
@ -438,7 +438,7 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> {
|
|||
///
|
||||
/// This function will build CGU names of the form:
|
||||
///
|
||||
/// ```
|
||||
/// ```text
|
||||
/// <crate-name>.<crate-disambiguator>[-in-<local-crate-id>](-<component>)*[.<special-suffix>]
|
||||
/// <local-crate-id> = <local-crate-name>.<local-crate-disambiguator>
|
||||
/// ```
|
||||
|
|
|
@ -202,7 +202,7 @@ pub enum TerminatorKind<'tcx> {
|
|||
/// This assignment occurs both in the unwind and the regular code paths. The semantics are best
|
||||
/// explained by the elaboration:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (MIR)
|
||||
/// BB0 {
|
||||
/// DropAndReplace(P <- V, goto BB1, unwind BB2)
|
||||
/// }
|
||||
|
@ -210,7 +210,7 @@ pub enum TerminatorKind<'tcx> {
|
|||
///
|
||||
/// becomes
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (MIR)
|
||||
/// BB0 {
|
||||
/// Drop(P, goto BB1, unwind BB2)
|
||||
/// }
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
//!
|
||||
//! For example, the `super_basic_block_data` method begins like this:
|
||||
//!
|
||||
//! ```rust
|
||||
//! ```ignore (pseudo-rust)
|
||||
//! fn super_basic_block_data(&mut self,
|
||||
//! block: BasicBlock,
|
||||
//! data: & $($mutability)? BasicBlockData<'tcx>) {
|
||||
|
@ -1170,10 +1170,10 @@ pub enum NonMutatingUseContext {
|
|||
AddressOf,
|
||||
/// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
|
||||
/// For example, the projection `x.y` is not marked as a mutation in these cases:
|
||||
///
|
||||
/// z = x.y;
|
||||
/// f(&x.y);
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// z = x.y;
|
||||
/// f(&x.y);
|
||||
/// ```
|
||||
Projection,
|
||||
}
|
||||
|
||||
|
@ -1199,10 +1199,10 @@ pub enum MutatingUseContext {
|
|||
AddressOf,
|
||||
/// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
|
||||
/// For example, the projection `x.y` is marked as a mutation in these cases:
|
||||
///
|
||||
/// x.y = ...;
|
||||
/// f(&mut x.y);
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// x.y = ...;
|
||||
/// f(&mut x.y);
|
||||
/// ```
|
||||
Projection,
|
||||
/// Retagging, a "Stacked Borrows" shadow state operation
|
||||
Retag,
|
||||
|
|
|
@ -47,7 +47,8 @@ pub enum Reveal {
|
|||
/// impl. Concretely, that means that the following example will
|
||||
/// fail to compile:
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,E0308
|
||||
/// #![feature(specialization)]
|
||||
/// trait Assoc {
|
||||
/// type Output;
|
||||
/// }
|
||||
|
@ -57,7 +58,7 @@ pub enum Reveal {
|
|||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let <() as Assoc>::Output = true;
|
||||
/// let x: <() as Assoc>::Output = true;
|
||||
/// }
|
||||
/// ```
|
||||
UserFacing,
|
||||
|
@ -515,7 +516,7 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
|
|||
/// For example, the obligation may be satisfied by a specific impl (case A),
|
||||
/// or it may be relative to some bound that is in scope (case B).
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1
|
||||
/// impl<T:Clone> Clone<T> for Box<T> { ... } // Impl_2
|
||||
/// impl Clone for i32 { ... } // Impl_3
|
||||
|
|
|
@ -180,6 +180,7 @@ pub struct LeafDef {
|
|||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(specialization)]
|
||||
/// trait Tr {
|
||||
/// fn assoc(&self);
|
||||
/// }
|
||||
|
|
|
@ -59,7 +59,7 @@ pub enum PointerCast {
|
|||
/// sized struct to a dynamically sized one. E.g., `&[i32; 4]` -> `&[i32]` is
|
||||
/// represented by:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// Deref(None) -> [i32; 4],
|
||||
/// Borrow(AutoBorrow::Ref) -> &[i32; 4],
|
||||
/// Unsize -> &[i32],
|
||||
|
|
|
@ -82,7 +82,7 @@ bitflags! {
|
|||
///
|
||||
/// is essentially represented with [`Ty`] as the following pseudocode:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// struct S { x }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -293,7 +293,7 @@ pub struct CaptureInfo {
|
|||
/// let mut t = (0,1);
|
||||
///
|
||||
/// let c = || {
|
||||
/// println!("{t}"); // L1
|
||||
/// println!("{t:?}"); // L1
|
||||
/// t.1 = 4; // L2
|
||||
/// };
|
||||
/// ```
|
||||
|
@ -309,7 +309,7 @@ pub struct CaptureInfo {
|
|||
/// let x = 5;
|
||||
///
|
||||
/// let c = || {
|
||||
/// let _ = x
|
||||
/// let _ = x;
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
|
@ -373,17 +373,19 @@ pub enum BorrowKind {
|
|||
/// is borrowing or mutating a mutable referent, e.g.:
|
||||
///
|
||||
/// ```
|
||||
/// let x: &mut isize = ...;
|
||||
/// let mut z = 3;
|
||||
/// let x: &mut isize = &mut z;
|
||||
/// let y = || *x += 5;
|
||||
/// ```
|
||||
///
|
||||
/// If we were to try to translate this closure into a more explicit
|
||||
/// form, we'd encounter an error with the code as written:
|
||||
///
|
||||
/// ```
|
||||
/// struct Env { x: & &mut isize }
|
||||
/// let x: &mut isize = ...;
|
||||
/// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
|
||||
/// ```compile_fail,E0594
|
||||
/// struct Env<'a> { x: &'a &'a mut isize }
|
||||
/// let mut z = 3;
|
||||
/// let x: &mut isize = &mut z;
|
||||
/// let y = (&mut Env { x: &x }, fn_ptr); // Closure is pair of env and fn
|
||||
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
|
||||
/// ```
|
||||
///
|
||||
|
@ -391,10 +393,11 @@ pub enum BorrowKind {
|
|||
/// in an aliasable location. To solve, you'd have to translate with
|
||||
/// an `&mut` borrow:
|
||||
///
|
||||
/// ```
|
||||
/// struct Env { x: &mut &mut isize }
|
||||
/// let x: &mut isize = ...;
|
||||
/// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
|
||||
/// ```compile_fail,E0596
|
||||
/// struct Env<'a> { x: &'a mut &'a mut isize }
|
||||
/// let mut z = 3;
|
||||
/// let x: &mut isize = &mut z;
|
||||
/// let y = (&mut Env { x: &mut x }, fn_ptr); // changed from &x to &mut x
|
||||
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -455,12 +455,13 @@ pub struct TypeckResults<'tcx> {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::fmt::Debug;
|
||||
/// fn foo(x: &u32) -> impl Debug { *x }
|
||||
/// ```
|
||||
///
|
||||
/// The function signature here would be:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(&'a u32) -> Foo
|
||||
/// ```
|
||||
///
|
||||
|
@ -469,7 +470,7 @@ pub struct TypeckResults<'tcx> {
|
|||
///
|
||||
/// The *liberated* form of this would be
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// fn(&'a u32) -> u32
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
//!
|
||||
//! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U:
|
||||
//! TypeFoldable`, and an instance `S(ty, u)`, it would be visited like so:
|
||||
//! ```
|
||||
//! ```text
|
||||
//! s.visit_with(visitor) calls
|
||||
//! - s.super_visit_with(visitor) calls
|
||||
//! - ty.visit_with(visitor) calls
|
||||
|
@ -486,13 +486,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// traversed. If we encounter a bound region bound by this
|
||||
/// binder or one outer to it, it appears free. Example:
|
||||
///
|
||||
/// ```
|
||||
/// for<'a> fn(for<'b> fn(), T)
|
||||
/// ^ ^ ^ ^
|
||||
/// | | | | here, would be shifted in 1
|
||||
/// | | | here, would be shifted in 2
|
||||
/// | | here, would be `INNERMOST` shifted in by 1
|
||||
/// | here, initially, binder would be `INNERMOST`
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(for<'b> fn(), T)
|
||||
/// // ^ ^ ^ ^
|
||||
/// // | | | | here, would be shifted in 1
|
||||
/// // | | | here, would be shifted in 2
|
||||
/// // | | here, would be `INNERMOST` shifted in by 1
|
||||
/// // | here, initially, binder would be `INNERMOST`
|
||||
/// ```
|
||||
///
|
||||
/// You see that, initially, *any* bound value is free,
|
||||
|
|
|
@ -56,7 +56,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// Checks whether a type is visibly uninhabited from a particular module.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// ```
|
||||
/// #![feature(never_type)]
|
||||
/// # fn main() {}
|
||||
/// enum Void {}
|
||||
/// mod a {
|
||||
/// pub mod b {
|
||||
|
@ -67,6 +69,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// }
|
||||
///
|
||||
/// mod c {
|
||||
/// use super::Void;
|
||||
/// pub struct AlsoSecretlyUninhabited {
|
||||
/// _priv: Void,
|
||||
/// }
|
||||
|
@ -84,7 +87,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// contain `Foo`.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// let foo_result: Result<T, Foo> = ... ;
|
||||
/// let Ok(t) = foo_result;
|
||||
/// ```
|
||||
|
|
|
@ -337,7 +337,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
/// Returns `Ok(None)` if we cannot resolve `Instance` to a specific instance.
|
||||
/// For example, in a context like this,
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// fn foo<T: Debug>(t: T) { ... }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -1012,9 +1012,9 @@ impl<'tcx> Predicate<'tcx> {
|
|||
/// their values.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// struct Foo<T, U: Bar<T>> { ... }
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// struct Foo<T, U: Bar<T>> { ... }
|
||||
/// ```
|
||||
/// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like
|
||||
/// `[[], [U:Bar<T>]]`. Now if there were some particular reference
|
||||
/// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[],
|
||||
|
@ -1072,9 +1072,9 @@ pub struct OpaqueHiddenType<'tcx> {
|
|||
/// The type variable that represents the value of the opaque type
|
||||
/// that we require. In other words, after we compile this function,
|
||||
/// we will be created a constraint like:
|
||||
///
|
||||
/// Foo<'a, T> = ?C
|
||||
///
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// Foo<'a, T> = ?C
|
||||
/// ```
|
||||
/// where `?C` is the value of this type variable. =) It may
|
||||
/// naturally refer to the type and lifetime parameters in scope
|
||||
/// in this function, though ultimately it should only reference
|
||||
|
@ -1115,7 +1115,7 @@ rustc_index::newtype_index! {
|
|||
///
|
||||
/// To make this more concrete, consider this program:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// struct Foo { }
|
||||
/// fn bar<T>(x: T) {
|
||||
/// let y: for<'a> fn(&'a u8, Foo) = ...;
|
||||
|
@ -1154,7 +1154,7 @@ impl UniverseIndex {
|
|||
/// corresponds to entering a `forall` quantifier. So, for
|
||||
/// example, suppose we have this type in universe `U`:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(&'a u32)
|
||||
/// ```
|
||||
///
|
||||
|
@ -1941,7 +1941,7 @@ pub enum ImplOverlapKind {
|
|||
/// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied
|
||||
/// that difference, making what reduces to the following set of impls:
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,(E0119)
|
||||
/// trait Trait {}
|
||||
/// impl Trait for dyn Send + Sync {}
|
||||
/// impl Trait for dyn Sync + Send {}
|
||||
|
|
|
@ -187,12 +187,14 @@ pub enum TyKind<'tcx> {
|
|||
/// Looking at the following example, the witness for this generator
|
||||
/// may end up as something like `for<'a> [Vec<i32>, &'a Vec<i32>]`:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore UNSOLVED (ask @compiler-errors, should this error? can we just swap the yields?)
|
||||
/// #![feature(generators)]
|
||||
/// |a| {
|
||||
/// let x = &vec![3];
|
||||
/// yield a;
|
||||
/// yield x[0];
|
||||
/// }
|
||||
/// # ;
|
||||
/// ```
|
||||
GeneratorWitness(Binder<'tcx, &'tcx List<Ty<'tcx>>>),
|
||||
|
||||
|
@ -276,9 +278,9 @@ impl<'tcx> TyKind<'tcx> {
|
|||
static_assert_size!(TyKind<'_>, 32);
|
||||
|
||||
/// A closure can be modeled as a struct that looks like:
|
||||
///
|
||||
/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U);
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U);
|
||||
/// ```
|
||||
/// where:
|
||||
///
|
||||
/// - 'l0...'li and T0...Tj are the generic parameters
|
||||
|
@ -295,25 +297,25 @@ static_assert_size!(TyKind<'_>, 32);
|
|||
/// and the up-var has the type `Foo`, then that field of U will be `&Foo`).
|
||||
///
|
||||
/// So, for example, given this function:
|
||||
///
|
||||
/// fn foo<'a, T>(data: &'a mut T) {
|
||||
/// do(|| data.count += 1)
|
||||
/// }
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// fn foo<'a, T>(data: &'a mut T) {
|
||||
/// do(|| data.count += 1)
|
||||
/// }
|
||||
/// ```
|
||||
/// the type of the closure would be something like:
|
||||
///
|
||||
/// struct Closure<'a, T, U>(...U);
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// struct Closure<'a, T, U>(...U);
|
||||
/// ```
|
||||
/// Note that the type of the upvar is not specified in the struct.
|
||||
/// You may wonder how the impl would then be able to use the upvar,
|
||||
/// if it doesn't know it's type? The answer is that the impl is
|
||||
/// (conceptually) not fully generic over Closure but rather tied to
|
||||
/// instances with the expected upvar types:
|
||||
///
|
||||
/// impl<'b, 'a, T> FnMut() for Closure<'a, T, (&'b mut &'a mut T,)> {
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<'b, 'a, T> FnMut() for Closure<'a, T, (&'b mut &'a mut T,)> {
|
||||
/// ...
|
||||
/// }
|
||||
/// ```
|
||||
/// You can see that the *impl* fully specified the type of the upvar
|
||||
/// and thus knows full well that `data` has type `&'b mut &'a mut T`.
|
||||
/// (Here, I am assuming that `data` is mut-borrowed.)
|
||||
|
@ -760,9 +762,9 @@ impl<'tcx> UpvarSubsts<'tcx> {
|
|||
}
|
||||
|
||||
/// An inline const is modeled like
|
||||
///
|
||||
/// const InlineConst<'l0...'li, T0...Tj, R>: R;
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// const InlineConst<'l0...'li, T0...Tj, R>: R;
|
||||
/// ```
|
||||
/// where:
|
||||
///
|
||||
/// - 'l0...'li and T0...Tj are the generic parameters
|
||||
|
@ -936,9 +938,9 @@ impl<'tcx> List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>> {
|
|||
|
||||
/// A complete reference to a trait. These take numerous guises in syntax,
|
||||
/// but perhaps the most recognizable form is in a where-clause:
|
||||
///
|
||||
/// T: Foo<U>
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// T: Foo<U>
|
||||
/// ```
|
||||
/// This would be represented by a trait-reference where the `DefId` is the
|
||||
/// `DefId` for the trait `Foo` and the substs define `T` as parameter 0,
|
||||
/// and `U` as parameter 1.
|
||||
|
@ -1012,9 +1014,9 @@ impl<'tcx> PolyTraitRef<'tcx> {
|
|||
|
||||
/// An existential reference to a trait, where `Self` is erased.
|
||||
/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
|
||||
///
|
||||
/// exists T. T: Trait<'a, 'b, X, Y>
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// exists T. T: Trait<'a, 'b, X, Y>
|
||||
/// ```
|
||||
/// The substitutions don't include the erased `Self`, only trait
|
||||
/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
|
||||
|
@ -1434,7 +1436,7 @@ impl<'tcx> fmt::Debug for Region<'tcx> {
|
|||
///
|
||||
/// In general, the region lattice looks like
|
||||
///
|
||||
/// ```
|
||||
/// ```text
|
||||
/// static ----------+-----...------+ (greatest)
|
||||
/// | | |
|
||||
/// early-bound and | |
|
||||
|
@ -1780,14 +1782,14 @@ impl<'tcx> Region<'tcx> {
|
|||
/// Given an early-bound or free region, returns the `DefId` where it was bound.
|
||||
/// For example, consider the regions in this snippet of code:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<'a> Foo {
|
||||
/// ^^ -- early bound, declared on an impl
|
||||
/// // ^^ -- early bound, declared on an impl
|
||||
///
|
||||
/// fn bar<'b, 'c>(x: &self, y: &'b u32, z: &'c u64) where 'static: 'c
|
||||
/// ^^ ^^ ^ anonymous, late-bound
|
||||
/// | early-bound, appears in where-clauses
|
||||
/// late-bound, appears only in fn args
|
||||
/// // ^^ ^^ ^ anonymous, late-bound
|
||||
/// // | early-bound, appears in where-clauses
|
||||
/// // late-bound, appears only in fn args
|
||||
/// {..}
|
||||
/// }
|
||||
/// ```
|
||||
|
|
|
@ -687,17 +687,17 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
|
|||
///
|
||||
/// ```
|
||||
/// type Func<A> = fn(A);
|
||||
/// type MetaFunc = for<'a> fn(Func<&'a i32>)
|
||||
/// type MetaFunc = for<'a> fn(Func<&'a i32>);
|
||||
/// ```
|
||||
///
|
||||
/// The type `MetaFunc`, when fully expanded, will be
|
||||
///
|
||||
/// for<'a> fn(fn(&'a i32))
|
||||
/// ^~ ^~ ^~~
|
||||
/// | | |
|
||||
/// | | DebruijnIndex of 2
|
||||
/// Binders
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(fn(&'a i32))
|
||||
/// // ^~ ^~ ^~~
|
||||
/// // | | |
|
||||
/// // | | DebruijnIndex of 2
|
||||
/// // Binders
|
||||
/// ```
|
||||
/// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the
|
||||
/// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip
|
||||
/// over the inner binder (remember that we count De Bruijn indices from 1). However, in the
|
||||
|
@ -709,17 +709,17 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
|
|||
///
|
||||
/// ```
|
||||
/// type FuncTuple<A> = (A,fn(A));
|
||||
/// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>)
|
||||
/// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>);
|
||||
/// ```
|
||||
///
|
||||
/// Here the final type will be:
|
||||
///
|
||||
/// for<'a> fn((&'a i32, fn(&'a i32)))
|
||||
/// ^~~ ^~~
|
||||
/// | |
|
||||
/// DebruijnIndex of 1 |
|
||||
/// DebruijnIndex of 2
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn((&'a i32, fn(&'a i32)))
|
||||
/// // ^~~ ^~~
|
||||
/// // | |
|
||||
/// // DebruijnIndex of 1 |
|
||||
/// // DebruijnIndex of 2
|
||||
/// ```
|
||||
/// As indicated in the diagram, here the same type `&'a i32` is substituted once, but in the
|
||||
/// first case we do not increase the De Bruijn index and in the second case we do. The reason
|
||||
/// is that only in the second case have we passed through a fn binder.
|
||||
|
@ -767,7 +767,7 @@ pub struct UserSubsts<'tcx> {
|
|||
/// sometimes needed to constrain the type parameters on the impl. For
|
||||
/// example, in this code:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// struct Foo<T> { }
|
||||
/// impl<A> Foo<A> { fn method() { } }
|
||||
/// ```
|
||||
|
|
|
@ -975,7 +975,7 @@ impl<'tcx> ExplicitSelf<'tcx> {
|
|||
///
|
||||
/// Examples:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<'a> Foo for &'a T {
|
||||
/// // Legal declarations:
|
||||
/// fn method1(self: &&'a T); // ExplicitSelf::ByReference
|
||||
|
|
|
@ -34,7 +34,7 @@ impl<'tcx> TypeWalker<'tcx> {
|
|||
///
|
||||
/// Example: Imagine you are walking `Foo<Bar<i32>, usize>`.
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// let mut iter: TypeWalker = ...;
|
||||
/// iter.next(); // yields Foo
|
||||
/// iter.next(); // yields Bar<i32>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue