|
1 | 1 | ## Glossary
|
2 | 2 |
|
3 |
| -#### Aliasing |
4 |
| - |
5 |
| -*Aliasing* occurs when one pointer or reference points to a "span" of memory |
6 |
| -that overlaps with the span of another pointer or reference. A span of memory is |
7 |
| -similar to how a slice works: there's a base byte address as well as a length in |
8 |
| -bytes. |
9 |
| - |
10 |
| -**Note**: a full aliasing model for Rust, defining when aliasing is allowed |
11 |
| -and when not, has not yet been defined. The purpose of this definition is to |
12 |
| -define when aliasing *happens*, not when it is *allowed*. The most developed |
13 |
| -potential aliasing model so far is known as "Stacked Borrows", and can be found |
14 |
| -[here](https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md). |
15 |
| - |
16 |
| -Consider the following example: |
17 |
| - |
18 |
| -```rust |
19 |
| -fn main() { |
20 |
| - let u: u64 = 7_u64; |
21 |
| - let r: &u64 = &u; |
22 |
| - let s: &[u8] = unsafe { |
23 |
| - core::slice::from_raw_parts(&u as *const u64 as *const u8, 8) |
24 |
| - }; |
25 |
| - let (head, tail) = s.split_first().unwrap(); |
26 |
| -} |
27 |
| -``` |
28 |
| - |
29 |
| -In this case, both `r` and `s` alias each other, since they both point to all of |
30 |
| -the bytes of `u`. |
31 |
| - |
32 |
| -However, `head` and `tail` do not alias each other: `head` points to the first |
33 |
| -byte of `u` and `tail` points to the other seven bytes of `u` after it. Both `head` |
34 |
| -and `tail` alias `s`, any overlap is sufficient to count as an alias. |
35 |
| - |
36 |
| -The span of a pointer or reference is the size of the value being pointed to or referenced. |
37 |
| -Depending on the type, you can determine the size as follows: |
38 |
| - |
39 |
| -* For a type `T` that is [`Sized`](https://doc.rust-lang.org/core/marker/trait.Sized.html) |
40 |
| - The span length of a pointer or reference to `T` is found with `size_of::<T>()`. |
41 |
| -* When `T` is not `Sized` the story is a little tricker: |
42 |
| - * If you have a reference `r` you can use `size_of_val(r)` to determine the |
43 |
| - span of the reference. |
44 |
| - * If you have a pointer `p` you must unsafely convert that to a reference before |
45 |
| - you can use `size_of_val`. There is not currently a safe way to determine the |
46 |
| - span of a pointer to an unsized type. |
47 |
| - |
48 |
| -The [Data layout](./layout.md) chapter also has more information on the sizes of different types. |
49 |
| - |
50 |
| -One interesting side effect of these rules is that references and pointers to |
51 |
| -Zero Sized Types _never_ alias each other, because their span length is always 0 |
52 |
| -bytes. |
53 |
| - |
54 |
| -It is also important to know that LLVM IR has a `noalias` attribute that works |
55 |
| -somewhat differently from this definition. However, that's considered a low |
56 |
| -level detail of a particular Rust implementation. When programming Rust, the |
57 |
| -Abstract Rust Machine is intended to operate according to the definition here. |
58 |
| - |
59 | 3 | #### Interior mutability
|
60 | 4 |
|
61 | 5 | *Interior Mutation* means mutating memory where there also exists a live shared reference pointing to the same memory; or mutating memory through a pointer derived from a shared reference.
|
@@ -129,10 +73,44 @@ niches. For example, the "all bits uninitialized" is an invalid bit-pattern for
|
129 | 73 | `&mut T`, but this bit-pattern cannot be used by layout optimizations, and is not a
|
130 | 74 | niche.
|
131 | 75 |
|
| 76 | +#### Place |
| 77 | + |
| 78 | +A *place* (called "lvalue" in C and "glvalue" in C++) is the result of computing a [*place expression*][place-value-expr]. |
| 79 | +A place is basically a pointer (pointing to some location in memory, potentially carrying [provenance](#pointer-provenance)), but might contain more information such as size or alignment (the details will have to be determined as the Rust Abstract Machine gets specified more precisely). |
| 80 | +A place has a type. |
| 81 | +Places cannot be "stored" in memory, only [values](#value) can. |
| 82 | + |
| 83 | +The key operations on a place are: |
| 84 | +* storing a [value](#value) of the same type in it (when it is used on the left-hand side of an assignment), |
| 85 | +* turning it into a [pointer value](#value) (when it is used inside `&expr`), |
| 86 | +* and loading a [value](#value) of the same type from it (through the place-to-value coercion). |
| 87 | + |
| 88 | + |
| 89 | +#### Value |
| 90 | + |
| 91 | +A *value* (called "value of the expression" or "rvalue" in C and "prvalue" in C++) is what gets stored in a [place](#place), and also the result of computing a [*value expression*][place-value-expr]. |
| 92 | +A value has a type, and it denotes the abstract mathematical concept that is represented by data in our programs. |
| 93 | +For example, a value of type `u8` is a mathematical integer in the range `0..256`. |
| 94 | +Values can be (according to their type) turned into a list of bytes, which is called a [representation](#representation) of the value. |
| 95 | +Values are ephemeral; they arise during the computation of an instruction but are only ever persisted in memory through their representation. |
| 96 | +(This is comparable to how run-time data in a program is ephemeral and is only ever persisted in serialized form.) |
| 97 | + |
| 98 | +#### Representation (relation) |
| 99 | + |
| 100 | +A *representation* of a [value](#value) is a list of bytes that is used to store or "represent" that value in memory. |
| 101 | + |
| 102 | +We also sometimes speak of the *representation of a type*; this should more correctly be called the *representation relation* as it relates values of this type to lists of bytes that represent this value. |
| 103 | +The term "relation" here is used in the mathematical sense: the representation relation is a predicate that, given a value and a list of bytes, says whether this value is represented by that list of bytes (`val -> list byte -> Prop`). |
| 104 | + |
| 105 | +The relation should be functional for a fixed list of bytes (i.e., every list of bytes has at most one associated representation). |
| 106 | +It is partial in both directions: not all values have a representation (e.g. the mathematical integer `300` has no representation at type `u8`), and not all lists of bytes correspond to a value of a specific type (e.g. lists of the wrong size correspond to no value, and the list consisting of the single byte `0x10` corresponds to no value of type `bool`). |
| 107 | +For a fixed value, there can be many representations (e.g., when considering type `#[repr(C)] Pair(u8, u16)`, the second byte is a padding byte so changing it does not affect the value represented by a list of bytes). |
| 108 | + |
| 109 | +See the [value domain][value-domain] for an example how values and representation relations can be made more precise. |
132 | 110 |
|
133 | 111 | ### TODO
|
134 | 112 |
|
135 | 113 | * *tag*
|
136 |
| -* *rvalue* |
137 |
| -* *lvalue* |
138 |
| -* *representation* |
| 114 | + |
| 115 | +[value-domain]: https://github.com/rust-lang/unsafe-code-guidelines/tree/master/wip/value-domain.md |
| 116 | +[place-value-expr]: https://doc.rust-lang.org/reference/expressions.html#place-expressions-and-value-expressions |
0 commit comments