update internal terminology: Substs -> GenericArgs

This commit is contained in:
yukang 2023-08-20 16:30:19 +08:00 committed by Tshepang Mbambo
parent 4285421cd2
commit 384ac6ebbb
7 changed files with 57 additions and 57 deletions

View File

@ -23,7 +23,7 @@ Term | Meaning
<span id="double-ptr">double pointer</span> &nbsp; | A pointer with additional metadata. See "fat pointer" for more. <span id="double-ptr">double pointer</span> &nbsp; | A pointer with additional metadata. See "fat pointer" for more.
<span id="drop-glue">drop glue</span> &nbsp; | (internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types. <span id="drop-glue">drop glue</span> &nbsp; | (internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types.
<span id="dst">DST</span> &nbsp; | 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> &nbsp; | 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> &nbsp; | 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> &nbsp; | 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> &nbsp; | see "uninhabited type". <span id="empty-type">empty type</span> &nbsp; | see "uninhabited type".
<span id="fat-ptr">fat pointer</span> &nbsp; | 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> &nbsp; | 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> &nbsp; | 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> &nbsp; | 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)

View File

@ -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

View File

@ -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:
Lets look a bit more closely at that last substitution to see why we use indexes. If we want to Lets 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.

View File

@ -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

View File

@ -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

View File

@ -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>)

View File

@ -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
Well dig more into generics and substitutions in a little bit. `[u32]`. Well 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> {