diff --git a/src/kinds.md b/src/kinds.md index d811423a..bd483c86 100644 --- a/src/kinds.md +++ b/src/kinds.md @@ -1,31 +1,49 @@ # Kinds -A `ty::subst::Kind<'tcx>` represents some entity in the type system: currently -either a type (`Ty<'tcx>`) or a lifetime (`ty::Region<'tcx>`), though in the -future this will also include constants (`ty::Const<'tcx>`) to facilitate the -use of const generics. `Kind` is used for type and lifetime substitution (from -abstract type and lifetime parameters to concrete types and lifetimes). - -## `UnpackedKind` -As `Kind` itself is not type-safe (see [`Kind`](#kind)), the `UnpackedKind` enum -provides a more convenient and safe interface for dealing with kinds. To -convert from an `UnpackedKind` to a `Kind`, you can call `Kind::from` (or -`.into`). It should not be necessary to convert a `Kind` to an `UnpackedKind`: -instead, you should prefer to deal with `UnpackedKind`, converting it only when -passing it to `Subst` methods. - -## `Kind` -The actual `Kind` struct is optimised for space, storing the type or lifetime -as an interned pointer containing a mask identifying its kind (in the lowest -2 bits). +A `ty::subst::Kind<'tcx>` represents some entity in the type system: a type +(`Ty<'tcx>`), lifetime (`ty::Region<'tcx>`) or constant (`ty::Const<'tcx>`). +`Kind` is used to perform substitutions of generic parameters for concrete +arguments, such as when calling a function with generic parameters explicitly +with type arguments. Substitutions are represented using the +[`Subst` type](#subst) as described below. ## `Subst` -`ty::subst::Subst<'tcx>` is simply defined as a slice of `Kind<'tcx>`s -and acts as an ordered list of substitutions from kind parameters (i.e. -type and lifetime parameters) to kinds. +`ty::subst::Subst<'tcx>` is intuitively simply a slice of `Kind<'tcx>`s, +acting as an ordered list of substitutions from generic parameters to +concrete arguments (such as types, lifetimes and consts). For example, given a `HashMap` with two type parameters, `K` and `V`, an instantiation of the parameters, for example `HashMap`, would be represented by the substitution `&'tcx [tcx.types.i32, tcx.types.u32]`. `Subst` provides various convenience methods to instantiant substitutions -given item definitions. +given item definitions, which should generally be used rather than explicitly +constructing such substitution slices. + +## `Kind` +The actual `Kind` struct is optimised for space, storing the type, lifetime or +const as an interned pointer containing a mask identifying its kind (in the +lowest 2 bits). Unless you are working with the `Subst` implementation +specifically, you should generally not have to deal with `Kind` and instead +make use of the safe [`UnpackedKind`](#unpackedkind) abstraction. + +## `UnpackedKind` +As `Kind` itself is not type-safe, the `UnpackedKind` enum provides a more +convenient and safe interface for dealing with kinds. An `UnpackedKind` can +be converted to a raw `Kind` using `Kind::from()` (or simply `.into()` when +the context is clear). As mentioned earlier, substition lists store raw +`Kind`s, so before dealing with them, it is preferable to convert them to +`UnpackedKind`s first. This is done by calling the `.unpack()` method. + +```rust +// An example of unpacking and packing a kind. +fn deal_with_kind<'tcx>(kind: Kind<'tcx>) -> Kind<'tcx> { + // Unpack a raw `Kind` to deal with it safely. + let new_kind: UnpackedKind<'tcx> = match kind.unpack() { + UnpackedKind::Type(ty) => { /* ... */ } + UnpackedKind::Lifetime(lt) => { /* ... */ } + UnpackedKind::Const(ct) => { /* ... */ } + }; + // Pack the `UnpackedKind` to store it in a substitution list. + new_kind.into() +} +```