Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specify bit validity and padding of some types #1392

Merged
merged 14 commits into from
Sep 9, 2023
6 changes: 6 additions & 0 deletions src/types/boolean.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ boolean type for its operands, they evaluate using the rules of [boolean logic].
* `a < b` is the same as `!(a >= b)`
* `a <= b` is the same as `a == b | a < b`

## Bit validity

The single byte of a `bool` is guaranteed to be initialized (in other words,
`transmute::<bool, u8>(...)` is always sound -- but since some bit patterns
are invalid `bool`s, the inverse is not always sound).

[boolean logic]: https://en.wikipedia.org/wiki/Boolean_algebra
[enumerated type]: enum.md
[expressions]: ../expressions.md
Expand Down
5 changes: 5 additions & 0 deletions src/types/numeric.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,8 @@ within an object along with one byte past the end.
> `isize` are either 32-bit or 64-bit. As a consequence, 16-bit
> pointer support is limited and may require explicit care and acknowledgment
> from a library to support.

## Bit validity

For every numeric type, `T`, the bit validity of `T` is equivalent to the bit
validity of `[u8; size_of::<T>()]`. An uninitialized byte is not a valid `u8`.
10 changes: 10 additions & 0 deletions src/types/pointer.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ Raw pointers can be created directly using [`core::ptr::addr_of!`] for `*const`

The standard library contains additional 'smart pointer' types beyond references and raw pointers.

## Bit validity

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::<P>()]`.
joshlf marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RalfJung For my own edification, how does this interact with pointer-to-integer as casts? I can imagine a few possibilities (not mutually exclusive):

  • as casts are sound, but transmutations are not necessarily sound (even though you can emulate a transmutation by doing an as cast followed by a transmutation from usize)
  • the first bullet is true and pointer-to-integer as casts probably shouldn't have been allowed in safe Rust, but it's too late

Copy link
Member

@RalfJung RalfJung Sep 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current working model is that as casts are special:

In contrast:

Here, "transmute" refers to transmute but also any other way to re-interpret bytes at a different type, such as type punning through union field accesses and raw pointer casts.

All of these operations are safe and sound, but as their docs show, they behave quite differently and that can affect the soundness of later code that uses the values they produce.

Note that this is a prototype model, which has some unresolved problems and which is very much not stabilized.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay that all makes sense, thanks!

Note that this is a prototype model, which has some unresolved problems and which is very much not stabilized.

I always assume that of everything in this space unless documented otherwise :)


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).

[`core::ptr::addr_of!`]: ../../core/ptr/macro.addr_of.html
[`core::ptr::addr_of_mut!`]: ../../core/ptr/macro.addr_of_mut.html
[Interior mutability]: ../interior-mutability.md
Expand Down
6 changes: 6 additions & 0 deletions src/types/textual.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ is valid UTF-8. Calling a `str` method with a non-UTF-8 buffer can cause
Since `str` is a [dynamically sized type], it can only be instantiated through a
pointer type, such as `&str`.

## Bit validity

Every byte of a `char` is guaranteed to be initialized (in other words,
`transmute::<char, [u8; size_of::<char>()]>(...)` is always sound -- but since
some bit patterns are invalid `char`s, the inverse is not always sound).

[Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
[Undefined Behavior]: ../behavior-considered-undefined.md
[dynamically sized type]: ../dynamically-sized-types.md