From 7f019ec5c87da39fe0b9b5149e413d914528e945 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Thu, 22 Nov 2018 20:41:58 -0500 Subject: [PATCH] fixup --- src/exotic-sizes.md | 21 +++++++++++++++------ src/other-reprs.md | 2 +- src/repr-rust.md | 8 +++++--- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/exotic-sizes.md b/src/exotic-sizes.md index 857df18..8ca7117 100644 --- a/src/exotic-sizes.md +++ b/src/exotic-sizes.md @@ -14,7 +14,7 @@ known size or alignment. On the surface, this is a bit nonsensical: Rust *must* know the size and alignment of something in order to correctly work with it! In this regard, DSTs are not normal types. Because they lack a statically known size, these types can only exist behind a pointer. Any pointer to a -DST consequently becomes a *fat* pointer consisting of the pointer and the +DST consequently becomes a *wide* pointer consisting of the pointer and the information that "completes" them (more on this below). There are two major DSTs exposed by the language: @@ -67,6 +67,10 @@ fn main() { } ``` +(Yes, custom DSTs are a largely half-baked feature for now.) + + + # Zero Sized Types (ZSTs) @@ -157,11 +161,16 @@ because that wouldn't make sense. We recommend against modelling C's `void*` type with `*const Void`. A lot of people started doing that but quickly ran into trouble because -people want to convert raw pointers to references when doing FFI, and making an -`&Void` is Undefined Behaviour. `*const ()` (or equivalent) works just as well, -and can be made into a reference without any safety problems. The only downside -of modeling `void*` with `*const ()` is that attempts to read or write values -will silently succeed (doing nothing), instead of producing a compiler error. +Rust doesn't really have any safety guards against trying to instantiate +empty types with unsafe code, and if you do it, it's Undefined Behaviour. +This was especially problematic because developers had a habit of converting +raw pointers to references and `&Void` is *also* Undefined Behaviour to +construct. + +`*const ()` (or equivalent) works reasonably well for `void*`, and can be made +into a reference without any safety problems. It still doesn't prevent you from +trying to read or write values, but at least it compiles to a no-op instead +of UB. diff --git a/src/other-reprs.md b/src/other-reprs.md index 11723a6..363c888 100644 --- a/src/other-reprs.md +++ b/src/other-reprs.md @@ -29,7 +29,7 @@ passed through the FFI boundary. C, and is explicitly contrary to the behavior of an empty type in C++, which says they should still consume a byte of space. -* DST pointers (fat pointers) and tuples are not a concept +* DST pointers (wide pointers) and tuples are not a concept in C, and as such are never FFI-safe. * Enums with fields also aren't a concept in C or C++, but a valid bridging diff --git a/src/repr-rust.md b/src/repr-rust.md index a75fb29..584a9a0 100644 --- a/src/repr-rust.md +++ b/src/repr-rust.md @@ -5,9 +5,11 @@ alignment of a type specifies what addresses are valid to store the value at. A value with alignment `n` must only be stored at an address that is a multiple of `n`. So alignment 2 means you must be stored at an even address, and 1 means that you can be stored anywhere. Alignment is at least 1, and always a power -of 2. Most primitives are generally aligned to their size, although this is -platform-specific behavior. For example, on x86 `u64` and `f64` may be only -aligned to 4 (32 bits). +of 2. + +Primitives are usually aligned to their size, although this is +platform-specific behavior. For example, on x86 `u64` and `f64` are often +aligned to 4 bytes (32 bits). A type's size must always be a multiple of its alignment. This ensures that an array of that type may always be indexed by offsetting by a multiple of its