diff --git a/reference/src/glossary.md b/reference/src/glossary.md
index 3b9cf4f7..6a0bdde4 100644
--- a/reference/src/glossary.md
+++ b/reference/src/glossary.md
@@ -53,8 +53,16 @@ For some more information, see [this blog post](https://www.ralfj.de/blog/2018/0
 
 #### Layout
 
-The *layout* of a type defines its size and alignment as well as the offsets of its subobjects (e.g. fields of structs/unions/enum/... or elements of arrays).
-Moreover, the layout of a type records its *function call ABI* (or just *ABI* for short): how the type is passed *by value* across a function boundary.
+The *layout* of a type defines:
+
+* its size,
+* its alignment,
+* its field offsets (e.g. fields of structs, union, enums, arrays, ...)
+* its [niches](#niche),
+* its [call abi](#call-abi).
+
+Note: due to discriminant-elision optimizations, niches are required to compute
+the layout of, e.g., `Option<T>`, from the layout of `T`.
 
 Note: Originally, *layout* and *representation* were treated as synonyms, and Rust language features like the `#[repr]` attribute reflect this. 
 In this document, *layout* and *representation* are not synonyms.
@@ -73,6 +81,43 @@ niches. For example, the "all bits uninitialized" is an invalid bit-pattern for
 `&mut T`, but this bit-pattern cannot be used by layout optimizations, and is not a
 niche.
 
+#### Call ABI
+
+The *call ABI* determines how a type is passed *by value* across a function boundary.
+
+Note: The set of possible call ABIs is not stable. Currently, it consists of:
+
+```rust,ignore
+enum Abi {
+    Uninhabited,
+    Scalar(Scalar),
+    Vector {
+        element: Scalar,
+        count: u64
+    },
+    Aggregate {
+        // If true, the layout size of the aggregate is exact.
+        // Otherwise, the layout size of the aggregate is
+        // a lower bound.
+        sized: bool,
+    }
+}
+```
+
+where a `Scalar` is either a primitive integer, floating point, or a pointer to
+a sized type.
+
+For example, the call ABI of:
+
+* `i32` is `Scalar(I32)`,
+* `#[repr(C)] struct Wrapper(i32);` is `Aggregate { sized: true }`.
+* `#[repr(transparent)] struct Wrapper(i32);` is `Scalar(I32)`.
+
+The call ABI of `repr(Rust)` types is unspecified. The following is not
+guaranteed, but right now the call ABI of:
+
+* `/*#[repr(Rust)]*/ struct Wrapper(i32);` (without `repr(transparent)`) is also
+  `Scalar(I32)` - only larger `struct`s are aggregates.
 
 ### TODO
 
diff --git a/reference/src/layout/arrays-and-slices.md b/reference/src/layout/arrays-and-slices.md
index 375d1571..bf356fc5 100644
--- a/reference/src/layout/arrays-and-slices.md
+++ b/reference/src/layout/arrays-and-slices.md
@@ -10,8 +10,9 @@ The _offset_ of the first array element is `0`, that is, a pointer to the array
 and a pointer to its first element both point to the same memory address.
 
 The _alignment_ of array types is greater or equal to the alignment of its
-element type. If the element type is `repr(C)` the layout of the array is
-guaranteed to be the same as the layout of a C array with the same element type.
+element type. If the element type is `repr(C)` the size and alignment of the
+array is guaranteed to be the same as the size and alignment of a C array with
+the same element type.
 
 > **Note**: the type of array arguments in C function signatures, e.g., `void
 > foo(T x[N])`, decays to a pointer. That is, these functions do not take arrays
diff --git a/reference/src/layout/function-pointers.md b/reference/src/layout/function-pointers.md
index 3188fb05..e9fe4782 100644
--- a/reference/src/layout/function-pointers.md
+++ b/reference/src/layout/function-pointers.md
@@ -25,7 +25,7 @@ or the address of a function.
 
 ### Representation
 
-The ABI and layout of `(unsafe)? (extern "ABI")? fn(Args...) -> Ret`
+The size, alignment, and call ABI of `(unsafe)? (extern "ABI")? fn(Args...) -> Ret`
 is exactly that of the corresponding C type --
 the lack of a null value does not change this. 
 On common platforms, this means that `*const ()` and `fn(Args...) -> Ret` have
diff --git a/reference/src/layout/pointers.md b/reference/src/layout/pointers.md
index 336651ef..9d965578 100644
--- a/reference/src/layout/pointers.md
+++ b/reference/src/layout/pointers.md
@@ -28,15 +28,18 @@ and are at least one word.
 
 ### Notes
 
-The layouts of `&T`, `&mut T`, `*const T` and `*mut T` are the same.
+The size, alignment, and call ABI of `&T`, `&mut T`, `*const T` and `*mut T` are
+the same.
 
-If `T` is sized, references and pointers to `T` have a size and alignment of one
-word and have therefore the same layout as C pointers.
+If `T` is sized, the size, alignment, and call ABI of references and pointers to
+`T` is the same as that of C pointers.
 
-> **warning**: while the layout of references and pointers is compatible with
-> the layout of C pointers, references come with a _validity_ invariant that
-> does not allow them to be used when they could be `NULL`, unaligned, dangling,
-> or, in the case of `&mut T`, aliasing.
+> **warning**: while the size, alignment, and call ABI of references and
+> pointers is compatible with the layout of C pointers, references come with a
+> _validity_ invariant that does not allow them to be used when they could be
+> `NULL`, unaligned, dangling, or, in the case of `&mut T`, aliasing. Since the
+> niches of references and pointers are not the same, these types are not
+> layout-compatible with each other.
 
 We do not make any guarantees about the layout of
 multi-trait objects `&(dyn Trait1 + Trait2)` or references to other dynamically sized types,
@@ -53,7 +56,7 @@ struct DynObject {
 
 > **note**: In the layout of `&dyn mut Trait` the field `data` is of the type `*mut u8`.
 
-The layout of `&[T]` is the same as that of:
+The size, alignment, and call ABI of `&[T]` and `&mut [T]` are the same as that of:
 ```rust
 #[repr(C)]
 struct Slice<T> {
@@ -62,7 +65,11 @@ struct Slice<T> {
 }
 ```
 
-> **note**: In the layout of `&mut [T]` the field `ptr` is of the type `*mut T`.
+> **note**: the field `ptr` is of the type `*mut T` for `&mut [T]`.
 
-The layout of `&str` is the same as that of `&[u8]`, and the layout of `&mut str` is
-the same as that of `&mut [u8]`.
+The size, alignment, and call ABI of `&str` is the same as that of `&[u8]`, and
+the layout of `&mut str` is the same as that of `&mut [u8]`.
+
+#### Unresolved question
+
+* Does `&str` have the same niches as `&[u8]` ?
diff --git a/reference/src/layout/scalars.md b/reference/src/layout/scalars.md
index 7b647cbc..8170dfa9 100644
--- a/reference/src/layout/scalars.md
+++ b/reference/src/layout/scalars.md
@@ -10,9 +10,9 @@ layout `#[repr()]` flags.
 
 ## `bool`
 
-Rust's `bool` has the same layout as C17's` _Bool`, that is, its size and
-alignment are implementation-defined. Any `bool` can be cast into an integer,
-taking on the values 1 (`true`) or 0 (`false`).
+Rust's `bool` has the same layout as C17's` _Bool` which is
+implementation-defined. Any `bool` can be cast into an integer, taking on the
+values 1 (`true`) or 0 (`false`).
 
 > **Note**: on all platforms that Rust's currently supports, its size and
 > alignment are 1, and its ABI class is `INTEGER` - see [Rust Layout and ABIs].