From 412494e79dad99796d671165cac55c8d119e0d87 Mon Sep 17 00:00:00 2001 From: yukang Date: Sun, 20 Aug 2023 16:30:19 +0800 Subject: [PATCH] update internal terminology: Substs -> GenericArgs --- src/appendix/glossary.md | 2 +- src/early-late-bound.md | 22 ++++++------ src/generics.md | 41 +++++++++++----------- src/memory.md | 10 +++--- src/return-position-impl-trait-in-trait.md | 4 +-- src/rustdoc-internals.md | 4 +-- src/ty.md | 16 ++++----- 7 files changed, 49 insertions(+), 50 deletions(-) diff --git a/src/appendix/glossary.md b/src/appendix/glossary.md index 019d311382..398beb6dae 100644 --- a/src/appendix/glossary.md +++ b/src/appendix/glossary.md @@ -23,7 +23,7 @@ Term | Meaning double pointer   | A pointer with additional metadata. See "fat pointer" for more. drop glue   | (internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types. DST   | 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]`). -early-bound lifetime   | 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)) +early-bound lifetime   | 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)) empty type   | see "uninhabited type". fat pointer   | 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". free variable   | 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) diff --git a/src/early-late-bound.md b/src/early-late-bound.md index 8fb856742a..9a6a0b1399 100644 --- a/src/early-late-bound.md +++ b/src/early-late-bound.md @@ -1,8 +1,8 @@ # Early and Late Bound Parameter Definitions 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 -`for<'a> fn(&'a u32)` mean. Reading [the nomincon chapter](https://doc.rust-lang.org/nomicon/hrtb.html) +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) 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>`. @@ -21,7 +21,7 @@ fn foo<'a>(_: &'a u32) {} fn main() { 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); } ``` @@ -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. ```rust 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 // on the `FnDef`. accepts_hr_func(foo_early); - + // works, the substituted bound is `for<'a> FnDef: Fn(&'a u32, u32)` accepts_hr_func(foo_late); } @@ -85,7 +85,7 @@ making `generics_of` behave this way. ## What parameters are currently late bound 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. ### 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 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: ```rust impl OtherTrait for ::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 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. -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: +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: `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 instantiate the parameter with an infer var while still allowing the FnDef to not have the diff --git a/src/generics.md b/src/generics.md index 7512b3b47c..001a671000 100644 --- a/src/generics.md +++ b/src/generics.md @@ -1,4 +1,4 @@ -# Generics and substitutions +# Generics and GenericArgs Given a generic type `MyType`, 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 @@ -6,19 +6,18 @@ 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 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”). -Conceptually, you can think of `SubstsRef` as a list of types that are to be substituted for the -generic type parameters of the ADT. +In rustc this is done using [GenericArgsRef]. +Conceptually, you can think of `GenericArgsRef` as a list of types that are to be substituted for the generic type parameters of the ADT. -`SubstsRef` is a type alias of `&'tcx List>` (see [`List` rustdocs][list]). +`GenericArgsRef` is a type alias of `&'tcx List>` (see [`List` rustdocs][list]). [`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). 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 -[`GenericArg`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/struct.GenericArg.html -[`GenericArgKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/enum.GenericArgKind.html -[SubstsRef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/type.SubstsRef.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/enum.GenericArgKind.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 `&List` is only 32 bits. As a consequence, it cannot be "subsliced" (that only works if the @@ -36,10 +35,10 @@ struct 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 `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 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 [`Generics`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html) type. It @@ -113,29 +112,29 @@ 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 find the type of `foo.x`, we can get generic type of `x`, which is `Vec`. 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`, 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! 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`. 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 `MyStruct`: `Adt(Foo, &[Param(0), Param(1)])`. -**`subst`** How do we actually do the substitutions? There is a function for that too! You use -[`subst`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/struct.EarlyBinder.html#method.subst) to -replace a `SubstsRef` with another list of types. +**`instantiate`** How do we actually do the substitutions? There is a function for that too! You use +[`instantiate`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/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]. The exact details are not too important, but in this piece of code, we happen to be converting from the `rustc_hir::Ty` to -a real `ty::Ty`. You can see that we first get some substitutions (`substs`). Then we call -`type_of` to get a type and call `ty.subst(substs)` to get a new version of `ty` with -the substitutions made. +a real `ty::Ty`. You can see that we first get some args (`args`). Then we call +`type_of` to get a type and call `ty.instantiate(tcx, args)` to get a new 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 example, the index could be out of bounds or it could be the index of a lifetime when we were diff --git a/src/memory.md b/src/memory.md index e5122deb21..83c0e0e796 100644 --- a/src/memory.md +++ b/src/memory.md @@ -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 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 - specify the values to be substituted for generics (e.g. `HashMap` would be represented - as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`). +- [`GenericArgs`][subst], allocated with `mk_args` – this will intern a slice of types, often used to +specify the values to be substituted for generics args(e.g. `HashMap` would be +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 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. - [`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 [`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html diff --git a/src/return-position-impl-trait-in-trait.md b/src/return-position-impl-trait-in-trait.md index 2ad9494e8c..03c7fb6b7a 100644 --- a/src/return-position-impl-trait-in-trait.md +++ b/src/return-position-impl-trait-in-trait.md @@ -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 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 -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- or late-bound during AST lowering, we just do this for all lifetimes. @@ -355,7 +355,7 @@ error[E0308]: mismatched types #### 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 duplicated early-bound lifetimes to their original lifetimes, and we diff --git a/src/rustdoc-internals.md b/src/rustdoc-internals.md index e78c4bb251..c35f01549a 100644 --- a/src/rustdoc-internals.md +++ b/src/rustdoc-internals.md @@ -26,7 +26,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> | rbv::ResolvedArg::Free(_, node_id), ) = 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; } } @@ -109,7 +109,7 @@ Here is the list of passes as of March 2023: `Go to https://example.com/.` It suggests wrapping the link with angle brackets: `Go to .` to linkify it. This is the code behind the `rustdoc::bare_urls` lint. - + - `check_code_block_syntax` validates syntax inside Rust code blocks (```rust) diff --git a/src/ty.md b/src/ty.md index 624fa42119..bea3c5144f 100644 --- a/src/ty.md +++ b/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 [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 -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` for any `T` be unified with `Vec`?". [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 @@ -287,7 +287,7 @@ struct MyStruct { x: u32, y: T } The type `MyStruct` would be an instance of `TyKind::Adt`: ```rust,ignore -Adt(&'tcx AdtDef, SubstsRef<'tcx>) +Adt(&'tcx AdtDef, GenericArgsRef<'tcx>) // ------------ --------------- // (1) (2) // @@ -301,12 +301,12 @@ There are two parts: 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`, 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 for the generic parameters. In our example of `MyStruct`, we would end up with a list like `[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 -[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`** @@ -363,13 +363,13 @@ delaying a redundant span bug. ## 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, 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 struct MyStruct {