|
| 1 | +# Generic arguments |
| 2 | +A `ty::subst::GenericArg<'tcx>` represents some entity in the type system: a type |
| 3 | +(`Ty<'tcx>`), lifetime (`ty::Region<'tcx>`) or constant (`ty::Const<'tcx>`). |
| 4 | +`GenericArg` is used to perform substitutions of generic parameters for concrete |
| 5 | +arguments, such as when calling a function with generic parameters explicitly |
| 6 | +with type arguments. Substitutions are represented using the |
| 7 | +[`Subst` type](#subst) as described below. |
| 8 | + |
| 9 | +## `Subst` |
| 10 | +`ty::subst::Subst<'tcx>` is intuitively simply a slice of `GenericArg<'tcx>`s, |
| 11 | +acting as an ordered list of substitutions from generic parameters to |
| 12 | +concrete arguments (such as types, lifetimes and consts). |
| 13 | + |
| 14 | +For example, given a `HashMap<K, V>` with two type parameters, `K` and `V`, an |
| 15 | +instantiation of the parameters, for example `HashMap<i32, u32>`, would be |
| 16 | +represented by the substitution `&'tcx [tcx.types.i32, tcx.types.u32]`. |
| 17 | + |
| 18 | +`Subst` provides various convenience methods to instantiate substitutions |
| 19 | +given item definitions, which should generally be used rather than explicitly |
| 20 | +constructing such substitution slices. |
| 21 | + |
| 22 | +## `GenericArg` |
| 23 | +The actual `GenericArg` struct is optimised for space, storing the type, lifetime or |
| 24 | +const as an interned pointer containing a tag identifying its kind (in the |
| 25 | +lowest 2 bits). Unless you are working with the `Subst` implementation |
| 26 | +specifically, you should generally not have to deal with `GenericArg` and instead |
| 27 | +make use of the safe [`GenericArgKind`](#genericargkind) abstraction. |
| 28 | + |
| 29 | +## `GenericArgKind` |
| 30 | +As `GenericArg` itself is not type-safe, the `GenericArgKind` enum provides a more |
| 31 | +convenient and safe interface for dealing with generic arguments. An |
| 32 | +`GenericArgKind` can be converted to a raw `GenericArg` using `GenericArg::from()` |
| 33 | +(or simply `.into()` when the context is clear). As mentioned earlier, substitution |
| 34 | +lists store raw `GenericArg`s, so before dealing with them, it is preferable to |
| 35 | +convert them to `GenericArgKind`s first. This is done by calling the `.unpack()` |
| 36 | +method. |
| 37 | + |
| 38 | +```rust,ignore |
| 39 | +// An example of unpacking and packing a generic argument. |
| 40 | +fn deal_with_generic_arg<'tcx>(generic_arg: GenericArg<'tcx>) -> GenericArg<'tcx> { |
| 41 | + // Unpack a raw `GenericArg` to deal with it safely. |
| 42 | + let new_generic_arg: GenericArgKind<'tcx> = match generic_arg.unpack() { |
| 43 | + GenericArgKind::Type(ty) => { /* ... */ } |
| 44 | + GenericArgKind::Lifetime(lt) => { /* ... */ } |
| 45 | + GenericArgKind::Const(ct) => { /* ... */ } |
| 46 | + }; |
| 47 | + // Pack the `GenericArgKind` to store it in a substitution list. |
| 48 | + new_generic_arg.into() |
| 49 | +} |
| 50 | +``` |
0 commit comments