Skip to content

Commit 1b7416e

Browse files
committed
Add some missing sections to the types system section
1 parent eeb1281 commit 1b7416e

File tree

4 files changed

+105
-17
lines changed

4 files changed

+105
-17
lines changed

src/SUMMARY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232

3333
- [Type system](type-system.md)
3434
- [Types](types.md)
35+
- [Dynamically Sized Types](dynamically-sized-types.md)
36+
- [Interior mutability](interior-mutability.md)
3537
- [Subtyping](subtyping.md)
3638
- [Type coercions](type-coercions.md)
3739

src/dynamically-sized-types.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Dynamically Sized Types
2+
3+
Most types have a fixed size that is known at compile time and implement the
4+
trait [`Sized`][sized]. A type with a size that is known only at run-time is
5+
called a _dynamically sized type_ (_DST_) or (informally) an unsized type.
6+
[Slices] and [trait objects] are two examples of <abbr title="dynamically sized
7+
types">DSTs</abbr>. Such types can only be used in certain cases:
8+
9+
* [Pointer types] to <abbr title="dynamically sized types">DSTs</abbr> are
10+
sized but have twice the size of pointers to sized types
11+
* Pointers to slices also store the number of elements of the slice.
12+
* Pointers to trait objects also store a pointer to a vtable.
13+
* <abbr title="dynamically sized types">DSTs</abbr> can be provided as
14+
type arguments when a bound of `?Sized`. By default any type parameter
15+
has a `?Sized` bound.
16+
* Traits may be implemented for <abbr title="dynamically sized
17+
types">DSTs</abbr>. Unlike type parameters`Self: ?Sized` by default in trait
18+
definitions.
19+
* Structs may contain a <abbr title="dynamically sized type">DST</abbr> as the
20+
last field, this makes the struct itself a
21+
<abbr title="dynamically sized type">DST</abbr>.
22+
23+
Notably: [variables], function parameters, [const] and [static] items must be
24+
`Sized`.
25+
26+
[sized]: the-sized-trait.html
27+
[Slices]: #array-and-slice-types
28+
[trait objects]: #trait-objects
29+
[Pointer types]: #pointer-types
30+
[variables]: variables.html
31+
[const]: items.html#constant-items
32+
[static]: items.html#static-items

src/interior-mutability.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Interior Mutability
2+
3+
Sometimes a type needs be mutated while having multiple aliases, in Rust this
4+
is achieved using a pattern called _interior mutability_. A type has interior
5+
mutability if its internal state can be changed through a [shared reference] to
6+
it. This goes against the usual [requirement][ub] that the value pointed to by a
7+
shared reference is not mutated.
8+
9+
[`std::cell::UnsafeCell<T>`] type is the only legal way in Rust to disable this
10+
requirement. When `UnsafeCell<T>` is immutably aliased, it is still safe to
11+
mutate, or obtain a mutable reference to, the `T` it contains. As with all
12+
other types, it is undefined behavior to have multiple `&mut UnsafeCell<T>`
13+
aliases.
14+
15+
Other types with interior mutability can be created by using `UnsafeCell<T>` as
16+
a field. The standard library provides a variety of types that provide safe
17+
interior mutability APIs. For example, [`std::cell::RefCell<T>`] uses run-time
18+
borrow checks to ensure the usual rules around multiple references. The
19+
[`std::sync::atomic`] module contains types that wrap a value that is only
20+
accessed with atomic operations, allowing the value to be shared and mutated
21+
across threads.
22+
23+
[shared reference]: types.hmtl#shared-references
24+
[ub]: behavior-considered-undefined.html
25+
[`std::mem::transmute`]: ../std/mem/fn.transmute.html
26+
[`std::cell::UnsafeCell<T>`]: ../std/cell/struct.UnsafeCell.html
27+
[`std::cell::RefCell<T>`]: ../std/cell/struct.RefCell.html
28+
[`std::sync::atomic`]: ../std/sync/atomic.html
29+
30+

src/types.md

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ Tuple types and values are denoted by listing the types or values of their
9393
elements, respectively, in a parenthesized, comma-separated list.
9494

9595
Because tuple elements don't have a name, they can only be accessed by
96-
pattern-matching or by using `N` directly as a field to access the
97-
`N`th element.
96+
pattern-matching or by using `N` directly as a field to access the `N`th
97+
element.
9898

9999
An example of a tuple type and its use:
100100

@@ -149,7 +149,7 @@ array or slice is always bounds-checked in safe methods and operators.
149149
The [`Vec<T>`] standard library type provides a heap allocated resizable array
150150
type.
151151

152-
[dynamically sized type]: #dynamically-sized-types
152+
[dynamically sized type]: dynamically-sized-types.html
153153
[`Vec<T>`]: ../std/vec/struct.Vec.html
154154

155155
## Struct types
@@ -162,13 +162,13 @@ expression](expressions.html#struct-expressions).
162162

163163
The memory layout of a `struct` is undefined by default to allow for compiler
164164
optimizations like field reordering, but it can be fixed with the
165-
`#[repr(...)]` attribute. In either case, fields may be given in any order in
166-
a corresponding struct *expression*; the resulting `struct` value will always
165+
`#[repr(...)]` attribute. In either case, fields may be given in any order in a
166+
corresponding struct *expression*; the resulting `struct` value will always
167167
have the same memory layout.
168168

169169
The fields of a `struct` may be qualified by [visibility
170-
modifiers](visibility-and-privacy.html), to allow access to data in a
171-
struct outside a module.
170+
modifiers](visibility-and-privacy.html), to allow access to data in a struct
171+
outside a module.
172172

173173
A _tuple struct_ type is just like a struct type, except that the fields are
174174
anonymous.
@@ -202,6 +202,21 @@ named reference to an [`enum` item](items.html#enumerations).
202202
[^enumtype]: The `enum` type is analogous to a `data` constructor declaration in
203203
ML, or a *pick ADT* in Limbo.
204204

205+
## Union types
206+
207+
A *union type* is a nominal, heterogeneous C-like union, denoted by the name of
208+
a [`union` item](items.html#unions).
209+
210+
A union contains the value of any one of its fields. Since the accessing the
211+
wrong field can cause unexpected or undefined behaviour, `unsafe` is required
212+
to read from a union field or to write to a field that doesn't implement
213+
[`Copy`].
214+
215+
The memory layout of a `union` is undefined by default, but the `#[repr(...)]`
216+
attribute can be used to fix a layout.
217+
218+
[`Copy`]: the-copy-trait.html
219+
205220
## Recursive types
206221

207222
Nominal types &mdash; [structs](#struct-types),
@@ -240,7 +255,7 @@ copied, stored into data structs, and returned from functions.
240255

241256
These point to memory _owned by some other value_. When a shared reference to a
242257
value is created it prevents direct mutation of the value. [Interior
243-
mutability](#interior-mutability) provides an exception for this in certain
258+
mutability](interior-mutability.html) provides an exception for this in certain
244259
circumstances. As the name suggests, any number of shared references to a value
245260
may exit. A shared reference type is written `&type`, or `&'a type` when you
246261
need to specify an explicit lifetime. Copying a reference is a "shallow"
@@ -249,6 +264,12 @@ operation: it involves only copying the pointer itself, that is, pointers are
249264
referencing of a [temporary value](expressions.html#temporary-lifetimes) will
250265
keep it alive during the scope of the reference itself.
251266

267+
### Mutable references (`&mut`)
268+
269+
These also point to memory owned by some other value. A mutable reference type
270+
is written `&mut type` or `&'a mut type`. A mutable reference (that hasn't been
271+
borrowed) is the only way to access the value it points to, so is not `Copy`.
272+
252273
### Raw pointers (`*const` and `*mut`)
253274

254275
Raw pointers are pointers without safety or liveness guarantees. Raw pointers
@@ -262,7 +283,8 @@ foreign code, and writing performance-critical or low-level functions.
262283

263284
When comparing pointers they are compared by their address, rather than by what
264285
they point to. When comparing pointers to [dynamically sized
265-
types](#dynamically-sized-types) they also have their addition data compared.
286+
types](dynamically-sized-types.html) they also have their addition data
287+
compared.
266288

267289
### Smart Pointers
268290

@@ -365,9 +387,9 @@ more of the closure traits:
365387
moved in the body of the closure. `Fn` inherits from `FnMut`, which itself
366388
inherits from `FnOnce`.
367389

368-
Closures that don't use anything from their environment ("non capturing closures")
369-
can be coerced to function pointers (`fn`) with the matching signature.
370-
To adopt the example from the section above:
390+
Closures that don't use anything from their environment ("non capturing
391+
closures") can be coerced to function pointers (`fn`) with the matching
392+
signature. To adopt the example from the section above:
371393

372394
```rust
373395
let add = |x, y| x + y;
@@ -382,9 +404,11 @@ x = bo(5,7);
382404
## Trait objects
383405

384406
In Rust, trait names also refer to [dynamically sized types] called _trait
385-
objects_. Like all DSTs, trait objects are used behind some kind of pointer:
386-
`&SomeTrait` or `Box<SomeTrait>`. Each instance of a pointer to a trait object
387-
includes:
407+
objects_. Like all <abbr title="dynamically sized types">DSTs</abbr>, trait
408+
objects are used behind some kind of pointer: `&SomeTrait` or `Box<SomeTrait>`.
409+
Each instance of a pointer to a trait object includes:
410+
411+
[dynamically sized types]: dynamically-sized-types.html
388412

389413
- a pointer to an instance of a type `T` that implements `SomeTrait`
390414
- a _virtual method table_, often just called a _vtable_, which contains, for
@@ -464,11 +488,11 @@ Box<Foo + 'static>
464488
impl Foo {}
465489
impl Foo + 'static {}
466490
467-
// ...so are these as &'a T requires T: 'a
491+
// ...so are these, because &'a T requires T: 'a
468492
&'a Foo
469493
&'a (Foo + 'a)
470494
471-
// ...std::cell::Ref<'a, T> also requires T: 'a, so these are also the same
495+
// std::cell::Ref<'a, T> also requires T: 'a, so these are the same
472496
std::cell::Ref<'a, Foo>
473497
std::cell::Ref<'a, Foo + 'a>
474498

0 commit comments

Comments
 (0)