update internal terminology: Substs -> GenericArgs
This commit is contained in:
parent
4285421cd2
commit
384ac6ebbb
|
|
@ -23,7 +23,7 @@ Term | Meaning
|
||||||
<span id="double-ptr">double pointer</span> | A pointer with additional metadata. See "fat pointer" for more.
|
<span id="double-ptr">double pointer</span> | A pointer with additional metadata. See "fat pointer" for more.
|
||||||
<span id="drop-glue">drop glue</span> | (internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types.
|
<span id="drop-glue">drop glue</span> | (internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types.
|
||||||
<span id="dst">DST</span> | Short for Dynamically-Sized Type, this is a type for which the compiler cannot statically know the size in memory (e.g. `str` or `[u8]`). Such types don't implement `Sized` and cannot be allocated on the stack. They can only occur as the last field in a struct. They can only be used behind a pointer (e.g. `&str` or `&[u8]`).
|
<span id="dst">DST</span> | Short for Dynamically-Sized Type, this is a type for which the compiler cannot statically know the size in memory (e.g. `str` or `[u8]`). Such types don't implement `Sized` and cannot be allocated on the stack. They can only occur as the last field in a struct. They can only be used behind a pointer (e.g. `&str` or `&[u8]`).
|
||||||
<span id="ebl">early-bound lifetime</span> | A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `Substs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html#bound-regions))
|
<span id="ebl">early-bound lifetime</span> | A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `GenericArgs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html#bound-regions))
|
||||||
<span id="empty-type">empty type</span> | see "uninhabited type".
|
<span id="empty-type">empty type</span> | see "uninhabited type".
|
||||||
<span id="fat-ptr">fat pointer</span> | A two word value carrying the address of some value, along with some further information necessary to put the value to use. Rust includes two kinds of "fat pointers": references to slices, and trait objects. A reference to a slice carries the starting address of the slice and its length. A trait object carries a value's address and a pointer to the trait's implementation appropriate to that value. "Fat pointers" are also known as "wide pointers", and "double pointers".
|
<span id="fat-ptr">fat pointer</span> | A two word value carrying the address of some value, along with some further information necessary to put the value to use. Rust includes two kinds of "fat pointers": references to slices, and trait objects. A reference to a slice carries the starting address of the slice and its length. A trait object carries a value's address and a pointer to the trait's implementation appropriate to that value. "Fat pointers" are also known as "wide pointers", and "double pointers".
|
||||||
<span id="free-var">free variable</span> | A "free variable" is one that is not bound within an expression or term; see [the background chapter for more](./background.md#free-vs-bound)
|
<span id="free-var">free variable</span> | A "free variable" is one that is not bound within an expression or term; see [the background chapter for more](./background.md#free-vs-bound)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# Early and Late Bound Parameter Definitions
|
# Early and Late Bound Parameter Definitions
|
||||||
|
|
||||||
Understanding this page likely requires a rudimentary understanding of higher ranked
|
Understanding this page likely requires a rudimentary understanding of higher ranked
|
||||||
trait bounds/`for<'a>`and also what types such as `dyn for<'a> Trait<'a>` and
|
trait bounds/`for<'a>`and also what types such as `dyn for<'a> Trait<'a>` and
|
||||||
`for<'a> fn(&'a u32)` mean. Reading [the nomincon chapter](https://doc.rust-lang.org/nomicon/hrtb.html)
|
`for<'a> fn(&'a u32)` mean. Reading [the nomincon chapter](https://doc.rust-lang.org/nomicon/hrtb.html)
|
||||||
on HRTB may be useful for understanding this syntax. The meaning of `for<'a> fn(&'a u32)`
|
on HRTB may be useful for understanding this syntax. The meaning of `for<'a> fn(&'a u32)`
|
||||||
is incredibly similar to the meaning of `T: for<'a> Trait<'a>`.
|
is incredibly similar to the meaning of `T: for<'a> Trait<'a>`.
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ fn foo<'a>(_: &'a u32) {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let b = foo;
|
let b = foo;
|
||||||
// ^ `b` has type `FnDef(foo, [])` (no substs because `'a` is late bound)
|
// ^ `b` has type `FnDef(foo, [])` (no args because `'a` is late bound)
|
||||||
assert!(std::mem::size_of_val(&b) == 0);
|
assert!(std::mem::size_of_val(&b) == 0);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -38,7 +38,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Because late bound parameters are not part of the `FnDef`'s substs this allows us to prove trait
|
Because late bound parameters are not part of the `FnDef`'s args this allows us to prove trait
|
||||||
bounds such as `F: for<'a> Fn(&'a u32)` where `F` is `foo`'s `FnDef`. e.g.
|
bounds such as `F: for<'a> Fn(&'a u32)` where `F` is `foo`'s `FnDef`. e.g.
|
||||||
```rust
|
```rust
|
||||||
fn foo_early<'a, T: Trait<'a>>(_: &'a u32, _: T) {}
|
fn foo_early<'a, T: Trait<'a>>(_: &'a u32, _: T) {}
|
||||||
|
|
@ -52,7 +52,7 @@ fn main() {
|
||||||
// of the borrow in the function argument must be the same as the lifetime
|
// of the borrow in the function argument must be the same as the lifetime
|
||||||
// on the `FnDef`.
|
// on the `FnDef`.
|
||||||
accepts_hr_func(foo_early);
|
accepts_hr_func(foo_early);
|
||||||
|
|
||||||
// works, the substituted bound is `for<'a> FnDef: Fn(&'a u32, u32)`
|
// works, the substituted bound is `for<'a> FnDef: Fn(&'a u32, u32)`
|
||||||
accepts_hr_func(foo_late);
|
accepts_hr_func(foo_late);
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +85,7 @@ making `generics_of` behave this way.
|
||||||
## What parameters are currently late bound
|
## What parameters are currently late bound
|
||||||
|
|
||||||
Below are the current requirements for determining if a generic parameter is late bound. It is worth
|
Below are the current requirements for determining if a generic parameter is late bound. It is worth
|
||||||
keeping in mind that these are not necessarily set in stone and it is almost certainly possible to
|
keeping in mind that these are not necessarily set in stone and it is almost certainly possible to
|
||||||
be more flexible.
|
be more flexible.
|
||||||
|
|
||||||
### Must be a lifetime parameter
|
### Must be a lifetime parameter
|
||||||
|
|
@ -161,7 +161,7 @@ this is simpler than the rules for checking impl headers constrain all the param
|
||||||
We only have to ensure that all late bound parameters appear at least once in the function argument
|
We only have to ensure that all late bound parameters appear at least once in the function argument
|
||||||
types outside of an alias (e.g. an associated type).
|
types outside of an alias (e.g. an associated type).
|
||||||
|
|
||||||
The requirement that they not indirectly be in the substs of an alias for it to count is the
|
The requirement that they not indirectly be in the args of an alias for it to count is the
|
||||||
same as why the follow code is forbidden:
|
same as why the follow code is forbidden:
|
||||||
```rust
|
```rust
|
||||||
impl<T: Trait> OtherTrait for <T as Trait>::Assoc { type Assoc = T }
|
impl<T: Trait> OtherTrait for <T as Trait>::Assoc { type Assoc = T }
|
||||||
|
|
@ -174,13 +174,13 @@ same is true of the builtin `Fn*` impls.
|
||||||
|
|
||||||
It is generally considered desirable for more parameters to be late bound as it makes
|
It is generally considered desirable for more parameters to be late bound as it makes
|
||||||
the builtin `Fn*` impls more flexible. Right now many of the requirements for making
|
the builtin `Fn*` impls more flexible. Right now many of the requirements for making
|
||||||
a parameter late bound are overly restrictive as they are tied to what we can currently
|
a parameter late bound are overly restrictive as they are tied to what we can currently
|
||||||
(or can ever) do with fn ptrs.
|
(or can ever) do with fn ptrs.
|
||||||
|
|
||||||
It would be theoretically possible to support late bound params in `where`-clauses in the
|
It would be theoretically possible to support late bound params in `where`-clauses in the
|
||||||
language by introducing implication types which would allow us to express types such as:
|
language by introducing implication types which would allow us to express types such as:
|
||||||
`for<'a, 'b: 'a> fn(Inv<&'a u32>, Inv<&'b u32>)` which would ensure `'b: 'a` is upheld when
|
`for<'a, 'b: 'a> fn(Inv<&'a u32>, Inv<&'b u32>)` which would ensure `'b: 'a` is upheld when
|
||||||
calling the function pointer.
|
calling the function pointer.
|
||||||
|
|
||||||
It would also be theoretically possible to support it by making the coercion to a fn ptr
|
It would also be theoretically possible to support it by making the coercion to a fn ptr
|
||||||
instantiate the parameter with an infer var while still allowing the FnDef to not have the
|
instantiate the parameter with an infer var while still allowing the FnDef to not have the
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generics and substitutions
|
# Generics and GenericArgs
|
||||||
|
|
||||||
Given a generic type `MyType<A, B, …>`, we may want to swap out the generics `A, B, …` for some
|
Given a generic type `MyType<A, B, …>`, we may want to swap out the generics `A, B, …` for some
|
||||||
other types (possibly other generics or concrete types). We do this a lot while doing type
|
other types (possibly other generics or concrete types). We do this a lot while doing type
|
||||||
|
|
@ -6,19 +6,20 @@ inference, type checking, and trait solving. Conceptually, during these routines
|
||||||
that one type is equal to another type and want to swap one out for the other and then swap that out
|
that one type is equal to another type and want to swap one out for the other and then swap that out
|
||||||
for another type and so on until we eventually get some concrete types (or an error).
|
for another type and so on until we eventually get some concrete types (or an error).
|
||||||
|
|
||||||
In rustc this is done using [SubstsRef] (“substs” = “substitutions”).
|
In rustc this is done using [GenericArgsRef].
|
||||||
Conceptually, you can think of `SubstsRef` as a list of types that are to be substituted for the
|
Conceptually, you can think of `GenericArgsRef` as a list of types that are to be substituted for
|
||||||
generic type parameters of the ADT.
|
the generic type parameters of the ADT.
|
||||||
|
|
||||||
`SubstsRef` is a type alias of `&'tcx List<GenericArg<'tcx>>` (see [`List` rustdocs][list]).
|
`GenericArgsRef` is a type alias of `&'tcx List<GenericArg<'tcx>>` (see [`List` rustdocs][list]).
|
||||||
[`GenericArg`] is essentially a space-efficient wrapper around [`GenericArgKind`], which is an enum
|
[`GenericArg`] is essentially a space-efficient wrapper around [`GenericArgKind`], which is an enum
|
||||||
indicating what kind of generic the type parameter is (type, lifetime, or const). Thus, `SubstsRef`
|
indicating what kind of generic the type parameter is (type, lifetime, or const).
|
||||||
is conceptually like a `&'tcx [GenericArgKind<'tcx>]` slice (but it is actually a `List`).
|
Thus, `GenericArgsRef` is conceptually like a `&'tcx [GenericArgKind<'tcx>]` slice (but it is
|
||||||
|
actually a `List`).
|
||||||
|
|
||||||
[list]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.List.html
|
[list]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.List.html
|
||||||
[`GenericArg`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/struct.GenericArg.html
|
[`GenericArg`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.GenericArg.html
|
||||||
[`GenericArgKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/enum.GenericArgKind.html
|
[`GenericArgKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.GenericArgKind.html
|
||||||
[SubstsRef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/type.SubstsRef.html
|
[GenericArgsRef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.GenericArgsRef.html
|
||||||
|
|
||||||
So why do we use this `List` type instead of making it really a slice? It has the length "inline",
|
So why do we use this `List` type instead of making it really a slice? It has the length "inline",
|
||||||
so `&List` is only 32 bits. As a consequence, it cannot be "subsliced" (that only works if the
|
so `&List` is only 32 bits. As a consequence, it cannot be "subsliced" (that only works if the
|
||||||
|
|
@ -36,10 +37,10 @@ struct MyStruct<T>
|
||||||
|
|
||||||
- There would be an `AdtDef` (and corresponding `DefId`) for `MyStruct`.
|
- There would be an `AdtDef` (and corresponding `DefId`) for `MyStruct`.
|
||||||
- There would be a `TyKind::Param` (and corresponding `DefId`) for `T` (more later).
|
- There would be a `TyKind::Param` (and corresponding `DefId`) for `T` (more later).
|
||||||
- There would be a `SubstsRef` containing the list `[GenericArgKind::Type(Ty(T))]`
|
- There would be a `GenericArgsRef` containing the list `[GenericArgKind::Type(Ty(T))]`
|
||||||
- The `Ty(T)` here is my shorthand for entire other `ty::Ty` that has `TyKind::Param`, which we
|
- The `Ty(T)` here is my shorthand for entire other `ty::Ty` that has `TyKind::Param`, which we
|
||||||
mentioned in the previous point.
|
mentioned in the previous point.
|
||||||
- This is one `TyKind::Adt` containing the `AdtDef` of `MyStruct` with the `SubstsRef` above.
|
- This is one `TyKind::Adt` containing the `AdtDef` of `MyStruct` with the `GenericArgsRef` above.
|
||||||
|
|
||||||
Finally, we will quickly mention the
|
Finally, we will quickly mention the
|
||||||
[`Generics`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html) type. It
|
[`Generics`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html) type. It
|
||||||
|
|
@ -113,33 +114,32 @@ This example has a few different substitutions:
|
||||||
|
|
||||||
Let’s look a bit more closely at that last substitution to see why we use indexes. If we want to
|
Let’s look a bit more closely at that last substitution to see why we use indexes. If we want to
|
||||||
find the type of `foo.x`, we can get generic type of `x`, which is `Vec<Param(0)>`. Now we can take
|
find the type of `foo.x`, we can get generic type of `x`, which is `Vec<Param(0)>`. Now we can take
|
||||||
the index `0` and use it to find the right type substitution: looking at `Foo`'s `SubstsRef`, we
|
the index `0` and use it to find the right type substitution: looking at `Foo`'s `GenericArgsRef`,
|
||||||
have the list `[u32, f32]` , since we want to replace index `0`, we take the 0-th index of this
|
we have the list `[u32, f32]` , since we want to replace index `0`, we take the 0-th index of this
|
||||||
list, which is `u32`. Voila!
|
list, which is `u32`. Voila!
|
||||||
|
|
||||||
You may have a couple of followup questions…
|
You may have a couple of followup questions…
|
||||||
|
|
||||||
**`type_of`** How do we get the “generic type of `x`"? You can get the type of pretty much anything
|
**`type_of`** How do we get the "generic type of `x`"? You can get the type of pretty much anything
|
||||||
with the `tcx.type_of(def_id)` query. In this case, we would pass the `DefId` of the field `x`.
|
with the `tcx.type_of(def_id)` query. In this case, we would pass the `DefId` of the field `x`.
|
||||||
The `type_of` query always returns the definition with the generics that are in scope of the
|
The `type_of` query always returns the definition with the generics that are in scope of the
|
||||||
definition. For example, `tcx.type_of(def_id_of_my_struct)` would return the “self-view” of
|
definition. For example, `tcx.type_of(def_id_of_my_struct)` would return the “self-view” of
|
||||||
`MyStruct`: `Adt(Foo, &[Param(0), Param(1)])`.
|
`MyStruct`: `Adt(Foo, &[Param(0), Param(1)])`.
|
||||||
|
|
||||||
**`subst`** How do we actually do the substitutions? There is a function for that too! You use
|
**`instantiate`** How do we actually do the substitutions? There is a function for that too! You
|
||||||
[`subst`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/struct.EarlyBinder.html#method.subst) to
|
use [`instantiate`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/
|
||||||
replace a `SubstsRef` with another list of types.
|
generic_args/struct.EarlyBinder.html#method.instantiate) to replace a `GenericArgsRef` with
|
||||||
|
another list of types.
|
||||||
|
|
||||||
[Here is an example of actually using `subst` in the compiler][substex]. The exact details are not
|
[Here is an example of actually using `instantiate` in the compiler][instantiatex].
|
||||||
too important, but in this piece of code, we happen to be converting from the `rustc_hir::Ty` to
|
The exact details are not too important, but in this piece of code, we happen to be
|
||||||
a real `ty::Ty`. You can see that we first get some substitutions (`substs`). Then we call
|
converting from the `rustc_hir::Ty` to a real `ty::Ty`. You can see that we first get some args
|
||||||
`type_of` to get a type and call `ty.subst(substs)` to get a new version of `ty` with
|
(`args`). Then we call `type_of` to get a type and call `ty.instantiate(tcx, args)` to get a new
|
||||||
the substitutions made.
|
version of `ty` with the args made.
|
||||||
|
|
||||||
[substex]: https://github.com/rust-lang/rust/blob/0940040c0486a536be4f8685c7dd9a078f9e87c2/compiler/rustc_hir_analysis/src/astconv/mod.rs#L1231-L1242
|
[instantiatex]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir_analysis/src/astconv/mod.rs#L905-L927
|
||||||
|
|
||||||
**Note on indices:** It is possible for the indices in `Param` to not match with what we expect. For
|
**Note on indices:** It is possible for the indices in `Param` to not match with what we expect. For
|
||||||
example, the index could be out of bounds or it could be the index of a lifetime when we were
|
example, the index could be out of bounds or it could be the index of a lifetime when we were
|
||||||
expecting a type. These sorts of errors would be caught earlier in the compiler when translating
|
expecting a type. These sorts of errors would be caught earlier in the compiler when translating
|
||||||
from a `rustc_hir::Ty` to a `ty::Ty`. If they occur later, that is a compiler bug.
|
from a `rustc_hir::Ty` to a `ty::Ty`. If they occur later, that is a compiler bug.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,16 +40,16 @@ to that buffer is freed and our `'tcx` references would be invalid.
|
||||||
In addition to types, there are a number of other arena-allocated data structures that you can
|
In addition to types, there are a number of other arena-allocated data structures that you can
|
||||||
allocate, and which are found in this module. Here are a few examples:
|
allocate, and which are found in this module. Here are a few examples:
|
||||||
|
|
||||||
- [`Substs`][subst], allocated with `mk_substs` – this will intern a slice of types, often used to
|
- [`GenericArgs`][subst], allocated with `mk_args` – this will intern a slice of types, often used
|
||||||
specify the values to be substituted for generics (e.g. `HashMap<i32, u32>` would be represented
|
to specify the values to be substituted for generics args(e.g. `HashMap<i32, u32>` would be
|
||||||
as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`).
|
represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`).
|
||||||
- [`TraitRef`], typically passed by value – a **trait reference** consists of a reference to a trait
|
- [`TraitRef`], typically passed by value – a **trait reference** consists of a reference to a trait
|
||||||
along with its various type parameters (including `Self`), like `i32: Display` (here, the def-id
|
along with its various type parameters (including `Self`), like `i32: Display` (here, the def-id
|
||||||
would reference the `Display` trait, and the substs would contain `i32`). Note that `def-id` is
|
would reference the `Display` trait, and the args would contain `i32`). Note that `def-id` is
|
||||||
defined and discussed in depth in the `AdtDef and DefId` section.
|
defined and discussed in depth in the `AdtDef and DefId` section.
|
||||||
- [`Predicate`] defines something the trait system has to prove (see `traits` module).
|
- [`Predicate`] defines something the trait system has to prove (see `traits` module).
|
||||||
|
|
||||||
[subst]: ./generic_arguments.html#subst
|
[`GenericArgs`]: ./generic_arguments.html#GenericArgs
|
||||||
[`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TraitRef.html
|
[`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TraitRef.html
|
||||||
[`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html
|
[`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ We record `lifetime_mapping`s for the opaque type, described below.
|
||||||
lifetimes into new lifetime parameters local to the opaque. The main
|
lifetimes into new lifetime parameters local to the opaque. The main
|
||||||
reason we do this is because RPITs need to be able to "reify"[^1] any
|
reason we do this is because RPITs need to be able to "reify"[^1] any
|
||||||
captured late-bound arguments, or make them into early-bound ones. This
|
captured late-bound arguments, or make them into early-bound ones. This
|
||||||
is so they can be used as substs for the opaque, and later to
|
is so they can be used as generic args for the opaque, and later to
|
||||||
instantiate hidden types. Since we don't know which lifetimes are early-
|
instantiate hidden types. Since we don't know which lifetimes are early-
|
||||||
or late-bound during AST lowering, we just do this for all lifetimes.
|
or late-bound during AST lowering, we just do this for all lifetimes.
|
||||||
|
|
||||||
|
|
@ -355,7 +355,7 @@ error[E0308]: mismatched types
|
||||||
|
|
||||||
#### Well-formedness checking
|
#### Well-formedness checking
|
||||||
|
|
||||||
We check well-formedness of RPITITs just like regular associated types.
|
We check well-formedness of RPITITs just like regular associated types.
|
||||||
|
|
||||||
Since we added lifetime bounds in `predicates_of` that link the
|
Since we added lifetime bounds in `predicates_of` that link the
|
||||||
duplicated early-bound lifetimes to their original lifetimes, and we
|
duplicated early-bound lifetimes to their original lifetimes, and we
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
|
||||||
| rbv::ResolvedArg::Free(_, node_id),
|
| rbv::ResolvedArg::Free(_, node_id),
|
||||||
) = def
|
) = def
|
||||||
{
|
{
|
||||||
if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
|
if let Some(lt) = cx.args.get(&node_id).and_then(|p| p.as_lt()).cloned() {
|
||||||
return lt;
|
return lt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -109,7 +109,7 @@ Here is the list of passes as of <!-- date-check --> March 2023:
|
||||||
`Go to https://example.com/.` It suggests wrapping the link with angle brackets:
|
`Go to https://example.com/.` It suggests wrapping the link with angle brackets:
|
||||||
`Go to <https://example.com/>.` to linkify it. This is the code behind the <!--
|
`Go to <https://example.com/>.` to linkify it. This is the code behind the <!--
|
||||||
date-check: may 2022 --> `rustdoc::bare_urls` lint.
|
date-check: may 2022 --> `rustdoc::bare_urls` lint.
|
||||||
|
|
||||||
- `check_code_block_syntax` validates syntax inside Rust code blocks
|
- `check_code_block_syntax` validates syntax inside Rust code blocks
|
||||||
(<code>```rust</code>)
|
(<code>```rust</code>)
|
||||||
|
|
||||||
|
|
|
||||||
20
src/ty.md
20
src/ty.md
|
|
@ -200,11 +200,11 @@ the function calls if one is available in some place (like during type checking)
|
||||||
If no inference context is available at all, then one can be created as described in
|
If no inference context is available at all, then one can be created as described in
|
||||||
[type-inference]. But this is only useful when the involved types (for example, if
|
[type-inference]. But this is only useful when the involved types (for example, if
|
||||||
they came from a query like `tcx.type_of()`) are actually substituted with fresh
|
they came from a query like `tcx.type_of()`) are actually substituted with fresh
|
||||||
inference variables using [`fresh_substs_for_item`]. This can be used to answer questions
|
inference variables using [`fresh_args_for_item`]. This can be used to answer questions
|
||||||
like "can `Vec<T>` for any `T` be unified with `Vec<u32>`?".
|
like "can `Vec<T>` for any `T` be unified with `Vec<u32>`?".
|
||||||
|
|
||||||
[type-inference]: ./type-inference.md#creating-an-inference-context
|
[type-inference]: ./type-inference.md#creating-an-inference-context
|
||||||
[`fresh_substs_for_item`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.fresh_substs_for_item
|
[`fresh_args_for_item`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.fresh_args_for_item
|
||||||
|
|
||||||
## `ty::TyKind` Variants
|
## `ty::TyKind` Variants
|
||||||
|
|
||||||
|
|
@ -287,7 +287,7 @@ struct MyStruct<T> { x: u32, y: T }
|
||||||
The type `MyStruct<u32>` would be an instance of `TyKind::Adt`:
|
The type `MyStruct<u32>` would be an instance of `TyKind::Adt`:
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
Adt(&'tcx AdtDef, SubstsRef<'tcx>)
|
Adt(&'tcx AdtDef, GenericArgsRef<'tcx>)
|
||||||
// ------------ ---------------
|
// ------------ ---------------
|
||||||
// (1) (2)
|
// (1) (2)
|
||||||
//
|
//
|
||||||
|
|
@ -301,12 +301,12 @@ There are two parts:
|
||||||
parameters. In our example, this is the `MyStruct` part *without* the argument `u32`.
|
parameters. In our example, this is the `MyStruct` part *without* the argument `u32`.
|
||||||
(Note that in the HIR, structs, enums and unions are represented differently, but in `ty::Ty`,
|
(Note that in the HIR, structs, enums and unions are represented differently, but in `ty::Ty`,
|
||||||
they are all represented using `TyKind::Adt`.)
|
they are all represented using `TyKind::Adt`.)
|
||||||
- The [`SubstsRef`][substsref] is an interned list of values that are to be substituted for the
|
- The [`GenericArgsRef`][GenericArgsRef] is an interned list of values that are to be substituted
|
||||||
generic parameters. In our example of `MyStruct<u32>`, we would end up with a list like `[u32]`.
|
for the generic parameters. In our example of `MyStruct<u32>`, we would end up with a list like
|
||||||
We’ll dig more into generics and substitutions in a little bit.
|
`[u32]`. We’ll dig more into generics and substitutions in a little bit.
|
||||||
|
|
||||||
[adtdef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.AdtDef.html
|
[adtdef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.AdtDef.html
|
||||||
[substsref]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/type.SubstsRef.html
|
[GenericArgsRef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/type.GenericArgsRef.html
|
||||||
|
|
||||||
**`AdtDef` and `DefId`**
|
**`AdtDef` and `DefId`**
|
||||||
|
|
||||||
|
|
@ -363,13 +363,13 @@ delaying a redundant span bug.
|
||||||
|
|
||||||
## Question: Why not substitute “inside” the `AdtDef`?
|
## Question: Why not substitute “inside” the `AdtDef`?
|
||||||
|
|
||||||
Recall that we represent a generic struct with `(AdtDef, substs)`. So why bother with this scheme?
|
Recall that we represent a generic struct with `(AdtDef, args)`. So why bother with this scheme?
|
||||||
|
|
||||||
Well, the alternate way we could have chosen to represent types would be to always create a new,
|
Well, the alternate way we could have chosen to represent types would be to always create a new,
|
||||||
fully-substituted form of the `AdtDef` where all the types are already substituted. This seems like
|
fully-substituted form of the `AdtDef` where all the types are already substituted. This seems like
|
||||||
less of a hassle. However, the `(AdtDef, substs)` scheme has some advantages over this.
|
less of a hassle. However, the `(AdtDef, args)` scheme has some advantages over this.
|
||||||
|
|
||||||
First, `(AdtDef, substs)` scheme has an efficiency win:
|
First, `(AdtDef, args)` scheme has an efficiency win:
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
struct MyStruct<T> {
|
struct MyStruct<T> {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue