()]`. An uninitialized byte is not a valid `u8`.
diff --git a/src/types/parameters.md b/src/types/parameters.md
index 7b9e7e64e..89b7df9ec 100644
--- a/src/types/parameters.md
+++ b/src/types/parameters.md
@@ -1,5 +1,7 @@
# Type parameters
+r[type.generic]
+
Within the body of an item that has type parameter declarations, the names of
its type parameters are types:
diff --git a/src/types/pointer.md b/src/types/pointer.md
index 7299ce75e..0f24d6bce 100644
--- a/src/types/pointer.md
+++ b/src/types/pointer.md
@@ -1,61 +1,96 @@
# Pointer types
+r[type.pointer]
+
+r[type.pointer.intro]
All pointers are explicit first-class values.
They can be moved or copied, stored into data structs, and returned from functions.
## References (`&` and `&mut`)
+r[type.pointer.reference]
+
+r[type.pointer.reference.syntax]
> **Syntax**\
> _ReferenceType_ :\
> `&` [_Lifetime_]? `mut`? [_TypeNoBounds_]
### Shared references (`&`)
+r[type.pointer.reference.shared]
+
+r[type.pointer.reference.shared.intro]
Shared references point to memory which is owned by some other value.
+
+r[type.pointer.reference.shared.constraint-mutation]
When a shared reference to a value is created, it prevents direct mutation of the value.
[Interior mutability] provides an exception for this in certain circumstances.
As the name suggests, any number of shared references to a value may exist.
A shared reference type is written `&type`, or `&'a type` when you need to specify an explicit lifetime.
+
+r[type.pointer.reference.shared.copy]
Copying a reference is a "shallow" operation:
it involves only copying the pointer itself, that is, pointers are `Copy`.
Releasing a reference has no effect on the value it points to, but referencing of a [temporary value] will keep it alive during the scope of the reference itself.
### Mutable references (`&mut`)
+r[type.pointer.reference.mut]
+
+r[type.pointer.reference.mut.intro]
Mutable references point to memory which is owned by some other value.
A mutable reference type is written `&mut type` or `&'a mut type`.
+
+r[type.pointer.reference.mut.copy]
A mutable reference (that hasn't been borrowed) is the only way to access the value it points to, so is not `Copy`.
## Raw pointers (`*const` and `*mut`)
+r[type.pointer.raw]
+
+r[type.pointer.raw.syntax]
> **Syntax**\
> _RawPointerType_ :\
> `*` ( `mut` | `const` ) [_TypeNoBounds_]
+r[type.pointer.raw.intro]
Raw pointers are pointers without safety or liveness guarantees.
Raw pointers are written as `*const T` or `*mut T`.
For example `*const i32` means a raw pointer to a 32-bit integer.
+
+r[type.pointer.raw.copy]
Copying or dropping a raw pointer has no effect on the lifecycle of any other value.
+
+r[type.pointer.raw.safety]
Dereferencing a raw pointer is an [`unsafe` operation].
+
This can also be used to convert a raw pointer to a reference by reborrowing it (`&*` or `&mut *`).
Raw pointers are generally discouraged;
they exist to support interoperability with foreign code, and writing performance-critical or low-level functions.
+r[type.pointer.raw.cmp]
When comparing raw pointers they are compared by their address, rather than by what they point to.
When comparing raw pointers to [dynamically sized types] they also have their additional data compared.
+r[type.pointer.raw.constructor]
Raw pointers can be created directly using `&raw const` for `*const` pointers and `&raw mut` for `*mut` pointers.
## Smart Pointers
+r[type.pointer.smart]
+
The standard library contains additional 'smart pointer' types beyond references and raw pointers.
## Bit validity
+r[type.pointer.validity]
+
+r[type.pointer.validity.pointer-fragment]
Despite pointers and references being similar to `usize`s in the machine code emitted on most platforms,
the semantics of transmuting a reference or pointer type to a non-pointer type is currently undecided.
Thus, it may not be valid to transmute a pointer or reference type, `P`, to a `[u8; size_of::()]`.
+r[type.pointer.validity.raw]
For thin raw pointers (i.e., for `P = *const T` or `P = *mut T` for `T: Sized`),
the inverse direction (transmuting from an integer or array of integers to `P`) is always valid.
However, the pointer produced via such a transmutation may not be dereferenced (not even if `T` has size zero).
diff --git a/src/types/slice.md b/src/types/slice.md
index 6ba5e7d21..79c340a87 100644
--- a/src/types/slice.md
+++ b/src/types/slice.md
@@ -1,12 +1,17 @@
# Slice types
+r[type.slice]
+
+r[type.slice.syntax]
> **Syntax**\
> _SliceType_ :\
> `[` [_Type_] `]`
+r[type.slice.intro]
A slice is a [dynamically sized type] representing a 'view' into a sequence of
elements of type `T`. The slice type is written as `[T]`.
+r[type.slice.unsized]
Slice types are generally used through pointer types. For example:
* `&[T]`: a 'shared slice', often just called a 'slice'. It doesn't own the
@@ -24,6 +29,7 @@ let boxed_array: Box<[i32]> = Box::new([1, 2, 3]);
let slice: &[i32] = &boxed_array[..];
```
+r[type.slice.safe]
All elements of slices are always initialized, and access to a slice is always
bounds-checked in safe methods and operators.
diff --git a/src/types/struct.md b/src/types/struct.md
index 1f20dbb3c..6a672f7af 100644
--- a/src/types/struct.md
+++ b/src/types/struct.md
@@ -1,22 +1,30 @@
# Struct types
+r[type.struct]
+
+r[type.struct.intro]
A `struct` *type* is a heterogeneous product of other types, called the
*fields* of the type.[^structtype]
+r[type.struct.constructor]
New instances of a `struct` can be constructed with a [struct expression].
+r[type.struct.layout]
The memory layout of a `struct` is undefined by default to allow for compiler
optimizations like field reordering, but it can be fixed with the
[`repr` attribute]. In either case, fields may be given in any order in a
corresponding struct *expression*; the resulting `struct` value will always
have the same memory layout.
+r[type.struct.field-visibility]
The fields of a `struct` may be qualified by [visibility modifiers], to allow
access to data in a struct outside a module.
+r[type.struct.tuple]
A _tuple struct_ type is just like a struct type, except that the fields are
anonymous.
+r[type.struct.unit]
A _unit-like struct_ type is like a struct type, except that it has no fields.
The one value constructed by the associated [struct expression] is the only
value that inhabits such a type.
diff --git a/src/types/textual.md b/src/types/textual.md
index a4765b523..e8515338c 100644
--- a/src/types/textual.md
+++ b/src/types/textual.md
@@ -1,26 +1,39 @@
# Textual types
+r[type.text]
+
+r[type.text.intro]
The types `char` and `str` hold textual data.
+r[type.text.char-value]
A value of type `char` is a [Unicode scalar value] (i.e. a code point that is
not a surrogate), represented as a 32-bit unsigned word in the 0x0000 to 0xD7FF
-or 0xE000 to 0x10FFFF range. It is immediate [undefined behavior] to create a
+or 0xE000 to 0x10FFFF range.
+
+r[type.text.char-precondition]
+It is immediate [undefined behavior] to create \1
`char` that falls outside this range. A `[char]` is effectively a UCS-4 / UTF-32
string of length 1.
+r[type.text.str-value]
A value of type `str` is represented the same way as `[u8]`, a slice of
8-bit unsigned bytes. However, the Rust standard library makes extra assumptions
about `str`: methods working on `str` assume and ensure that the data in there
is valid UTF-8. Calling a `str` method with a non-UTF-8 buffer can cause
[undefined behavior] now or in the future.
+r[type.text.str-unsized]
Since `str` is a [dynamically sized type], it can only be instantiated through a
pointer type, such as `&str`.
## Layout and bit validity
+r[type.text.layout]
+
+r[type.layout.char-layout]
`char` is guaranteed to have the same size and alignment as `u32` on all platforms.
+r[type.layout.char-validity]
Every byte of a `char` is guaranteed to be initialized (in other words,
`transmute::()]>(...)` is always sound -- but since
some bit patterns are invalid `char`s, the inverse is not always sound).
diff --git a/src/types/trait-object.md b/src/types/trait-object.md
index 5b8541fa8..598ad290b 100644
--- a/src/types/trait-object.md
+++ b/src/types/trait-object.md
@@ -1,5 +1,8 @@
# Trait objects
+r[type.trait-object]
+
+r[type.trait-object.syntax]
> **Syntax**\
> _TraitObjectType_ :\
> `dyn`? [_TypeParamBounds_]
@@ -7,16 +10,21 @@
> _TraitObjectTypeOneBound_ :\
> `dyn`? [_TraitBound_]
+r[type.trait-object.intro]
A *trait object* is an opaque value of another type that implements a set of
traits. The set of traits is made up of an [object safe] *base trait* plus any
number of [auto traits].
+r[type.trait-object.impls]
Trait objects implement the base trait, its auto traits, and any [supertraits]
of the base trait.
+r[type.trait-object.name]
Trait objects are written as the keyword `dyn` followed by a set of trait
-bounds, but with the following restrictions on the trait bounds. All traits
-except the first trait must be auto traits, there may not be more than one
+bounds, but with the following restrictions on the trait bounds.
+
+r[type.trait-object.constraint]
+All traits except the first trait must be auto traits, there may not be more than one
lifetime, and opt-out bounds (e.g. `?Sized`) are not allowed. Furthermore,
paths to traits may be parenthesized.
@@ -31,12 +39,14 @@ For example, given a trait `Trait`, the following are all trait objects:
* `dyn 'static + Trait`.
* `dyn (Trait)`
+r[type.trait-object.syntax-edition2021]
> **Edition differences**: Before the 2021 edition, the `dyn` keyword may be
> omitted.
>
> Note: For clarity, it is recommended to always use the `dyn` keyword on your
> trait objects unless your codebase supports compiling with Rust 1.26 or lower.
+r[type.trait-object.syntax-edition2015]
> **Edition differences**: In the 2015 edition, if the first bound of the
> trait object is a path that starts with `::`, then the `dyn` will be treated
> as a part of the path. The first path can be put in parenthesis to get
@@ -46,11 +56,13 @@ For example, given a trait `Trait`, the following are all trait objects:
> Beginning in the 2018 edition, `dyn` is a true keyword and is not allowed in
> paths, so the parentheses are not necessary.
+r[type.trait-object.alias]
Two trait object types alias each other if the base traits alias each other and
if the sets of auto traits are the same and the lifetime bounds are the same.
For example, `dyn Trait + Send + UnwindSafe` is the same as
`dyn Trait + UnwindSafe + Send`.
+r[type.trait-object.unsized]
Due to the opaqueness of which concrete type the value is of, trait objects are
[dynamically sized types]. Like all
DSTs, trait objects are used
@@ -93,6 +105,8 @@ type signature of `print`, and the cast expression in `main`.
## Trait Object Lifetime Bounds
+r[type.trait-object.lifetime-bounds]
+
Since a trait object can contain references, the lifetimes of those references
need to be expressed as part of the trait object. This lifetime is written as
`Trait + 'a`. There are [defaults] that allow this lifetime to usually be
diff --git a/src/types/tuple.md b/src/types/tuple.md
index 804d8a0ae..073fbd193 100644
--- a/src/types/tuple.md
+++ b/src/types/tuple.md
@@ -1,26 +1,35 @@
# Tuple types
+r[type.tuple]
+
+r[type.tuple.syntax]
> **Syntax**\
> _TupleType_ :\
> `(` `)`\
> | `(` ( [_Type_] `,` )+ [_Type_]? `)`
+r[type.tuple.intro]
*Tuple types* are a family of structural types[^1] for heterogeneous lists of other types.
The syntax for a tuple type is a parenthesized, comma-separated list of types.
+
+r[type.tuple.restriction]
1-ary tuples require a comma after their element type to be disambiguated with a [parenthesized type].
+r[type.tuple.field-number]
A tuple type has a number of fields equal to the length of the list of types.
This number of fields determines the *arity* of the tuple.
A tuple with `n` fields is called an *n-ary tuple*.
For example, a tuple with 2 fields is a 2-ary tuple.
+r[type.tuple.field-name]
Fields of tuples are named using increasing numeric names matching their position in the list of types.
The first field is `0`.
The second field is `1`.
And so on.
The type of each field is the type of the same position in the tuple's list of types.
+r[type.tuple.unit]
For convenience and historical reasons, the tuple type with no fields (`()`) is often called *unit* or *the unit type*.
Its one value is also called *unit* or *the unit value*.
@@ -33,8 +42,11 @@ Some examples of tuple types:
* `(i32, String)` (different type from the previous example)
* `(i32, f64, Vec, Option)`
+r[type.tuple.constructor]
Values of this type are constructed using a [tuple expression].
Furthermore, various expressions will produce the unit value if there is no other meaningful value for it to evaluate to.
+
+r[type.tuple.access]
Tuple fields can be accessed by either a [tuple index expression] or [pattern matching].
[^1]: Structural types are always equivalent if their internal types are equivalent.
diff --git a/src/types/union.md b/src/types/union.md
index 7a2f037e8..c8801ee2f 100644
--- a/src/types/union.md
+++ b/src/types/union.md
@@ -1,15 +1,25 @@
# Union types
+r[type.union]
+
+r[type.union.intro]
A *union type* is a nominal, heterogeneous C-like union, denoted by the name of
a [`union` item][item].
+r[type.union.access]
Unions have no notion of an "active field". Instead, every union access
transmutes parts of the content of the union to the type of the accessed field.
+
+r[type.union.safety]
Since transmutes can cause unexpected or undefined behaviour, `unsafe` is
-required to read from a union field. Union field types are also restricted to a
+required to read from a union field.
+
+r[type.union.constraint]
+Union field types are also restricted to a
subset of types which ensures that they never need dropping. See the [item]
documentation for further details.
+r[type.union.layout]
The memory layout of a `union` is undefined by default (in particular, fields do
*not* have to be at offset 0), but the `#[repr(...)]` attribute can be used to
fix a layout.