From 02652baf8d321db793d5ff4d76857af1377ab9c6 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 14 Mar 2019 17:57:39 +0100 Subject: [PATCH 01/11] Be more explicit about the layout guarantees of integer and floating-point types. --- .../src/layout/integers-floatingpoint.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/reference/src/layout/integers-floatingpoint.md b/reference/src/layout/integers-floatingpoint.md index 6dda3508..c95df7fc 100644 --- a/reference/src/layout/integers-floatingpoint.md +++ b/reference/src/layout/integers-floatingpoint.md @@ -38,6 +38,25 @@ Note: on all platforms that Rust's currently supports, the size and alignment of For full ABI compatibility details, see [Gankro’s post](https://gankro.github.io/blah/rust-layouts-and-abis/#the-layoutsabis-of-builtins). +## Fixed-width integer types + +Rust's fixed-width integer types `{i,u}{8,16,32,64}` have the same layout as the +C fixed-width integer types from the `` header +`{u,}int{8,16,32,64}_t`. That is: + +* these types have no padding bits, +* their size exactly matches their bit-width, +* negative values of signed integer types are represented using `2`'s complement. + +Therefore these integer types are safe to use directly in C FFI where the +fixed-width integer types are expected. + +## Fixed-width floating point types + +Rust's `f32` and `f64` types have the same layout as C's `float` and `double` +types, respectively. Therefore these floating-point types are safe to use +directly in C FFI where the appropriate C types are expected. + ## Relationship to C integer hierarchy C integers: - char: at least 8 bits From b6d30c50212114b69f4bde46b3458fa0db967319 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Fri, 15 Mar 2019 11:25:56 +0100 Subject: [PATCH 02/11] Re-word the whole document; add two FIXME's --- .../src/layout/integers-floatingpoint.md | 148 +++++++++++------- 1 file changed, 92 insertions(+), 56 deletions(-) diff --git a/reference/src/layout/integers-floatingpoint.md b/reference/src/layout/integers-floatingpoint.md index c95df7fc..bdd98348 100644 --- a/reference/src/layout/integers-floatingpoint.md +++ b/reference/src/layout/integers-floatingpoint.md @@ -1,80 +1,116 @@ # Layout of Boolean, Floating Point, and Integral Types -This chapter represents the consensus from issue [#9]. It documents the memory layout and considerations for `bool`, `usize`, `isize`, floating point types, and integral types. + +This chapter represents the consensus from issue [#9]. It documents the memory +layout and considerations for `bool`, floating point types (`f{32, 64}`), and +integral types (`{i,u}{8,16,32,64,128,size}`). + +These types are all scalar types, representing a single value, and have no +layout `#[repr()]` flags. [#9]: https://github.com/rust-rfcs/unsafe-code-guidelines/issues/9 -## Overview -These are all scalar types, representing a single value. These types have no layout variants (no `#[repr(C)]` or `#[repr(Rust)]`). Their size is fixed and well-defined across FFI boundaries and map to their corresponding integral types in the C ABI. -- `bool`: 1 byte - - any `bool` can be cast into an integer, taking on the values 1 (true) or 0 (false) -- `usize`, `isize`: pointer-sized unsigned/signed integer type -- `u8` .. `u128`, `i8` .. `i128` - - {8, 16, 32, 64, 128}-bit unsigned integer - - {8, 16, 32, 64, 128}-bit signed integer -- `f32`, `f64` - - IEEE floats - - 32-bit or 64-bit -- `char` - - C++ char: equivalent to either `i8`/`u8` - - Rust char: 32-bit - - not ABI compatible - - represents [Unicode scalar value](http://www.unicode.org/glossary/#unicode_scalar_value) +## `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`). + +> **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]. + +[Rust Layout and ABIs]: https://gankro.github.io/blah/rust-layouts-and-abis/#the-layoutsabis-of-builtins + +## `char` + +Rust char is 32-bit wide and represents [Unicode scalar value](http://www.unicode.org/glossary/#unicode_scalar_value). + +> **Note**: Rust `char` type is not layout compatible with C / C++ `char` types. +> The C / C++ `char` types correspond to either Rust's `i8` or `u8` types on all +> currently supported platforms, depending on their signedness. Rust does not +> support C platforms in which C `char` is not 8-bit wide. ## `usize`/`isize` -Types `usize` and `isize` are committed to having the same size as a native pointer on the platform. The layout of `usize` determines the following: -- how much a pointer of a certain type can be offseted, -- the maximum size of Rust objects (because size_of/size_of_val return `usize`), -- the maximum number of elements in an array (`[T; N: usize]`), -- `usize`/`isize` in C FFI are compatible with C's `uintptr_t` / `intptr_t` (and have the same size and alignment). -The maximum size of any single value must fit within `usize` to [ensure that pointer diff is representable](https://github.com/rust-rfcs/unsafe-code-guidelines/pull/5#discussion_r212703192). +The `usize` and `isize` types are pointer-sized signed and unsigned integers. +They have the same layout as the [pointer types] for which the pointee is +`Sized`, and are layout compatible with C's `uintptr_t` and `intptr_t` types. + +> **Note**: Rust's `usize` and C's `unsigned` types are **not** equivalent. C's +> `unsigned` is at least as large as a short, allowed to have padding bits, etc. +> but it is not necessarily pointer-sized. -`usize` and C’s `unsized` are *not* equivalent. +The layout of `usize` determines the following: -## Booleans -Rust's `bool` has the same layout as C17's` _Bool`, that is, its size and alignment are implementation-defined. +- the maximum size of Rust objects (`size_of` and `size_of_val` return `usize`), +- the maximum number of elements in an array (`[T; N: usize]`), +- how much a pointer of a certain type can be offseted (limited by `usize::max_value()`). + +> **FIXME**: Pointer `add` operates on `usize`, but pointer `offset` operates on +> `isize`, so unless by "offseted" we mean something different from `ptr.offset` +> above, `usize::max_value()` does not determine how much a pointer can be +> "offseted". We should probably be more specific here and call out `ptr.add` +> and `ptr.offset` explicitly. + +The maximum size of any single value must fit within `usize` to [ensure that +pointer diff is +representable](https://github.com/rust-rfcs/unsafe-code-guidelines/pull/5#discussion_r212703192). -Note: on all platforms that Rust's currently supports, the size and alignment of bool are 1, and its ABI class is INTEGER. +> **FIXME**: This does not make sense. We state that the layout of `usize` +> determines the maximum size of an object, and then argue that this is to +> ensure that pointer diff is representable, which won't be the case if the size +> of an object is `usize::max_val()`. The link cited actually states that, right +> now, the largest size of a Rust object is limited by `isize::max_value()`. -For full ABI compatibility details, see [Gankro’s post](https://gankro.github.io/blah/rust-layouts-and-abis/#the-layoutsabis-of-builtins). +[pointer types]: ./pointers.md ## Fixed-width integer types -Rust's fixed-width integer types `{i,u}{8,16,32,64}` have the same layout as the -C fixed-width integer types from the `` header +Rust's signed and unsigned fixed-width integer types `{i,u}{8,16,32,64}` have +the same layout as the C fixed-width integer types from the `` header `{u,}int{8,16,32,64}_t`. That is: * these types have no padding bits, * their size exactly matches their bit-width, -* negative values of signed integer types are represented using `2`'s complement. +* negative values of signed integer types are represented using 2's complement. + +This properties also hold for Rust's 128-bit wide `{i,u}128` integer types, but +C does not expose equivalent types in ``. + +Rust fixed-width integer types are therefore safe to use directly in C FFI where +the corresponding C fixed-width integer types are expected. +integer types are expected. -Therefore these integer types are safe to use directly in C FFI where the -fixed-width integer types are expected. +### Layout compatibility with C native integer types + +The specification of native C integer types, `char`, `short`, `int`, `long`, +... as well as their `unsigned` variants, has a lower bound on their size, +e.g., `short` is _at least_ 16-bit wide and _at least_ as wide as `char`. +Their actual exact sizes are _implementation-defined_. + +Libraries like `libc` use knowledge of this _implementation-defined_ behavior on +each platform to select a layout-compatible Rust fixed-width integer type when +interfacing with native C integer types. + +> **Note**: Rust does not support C platforms on which the C native integer type +> are not compatible with any of Rust's fixed-width integer type (e.g. because +> of padding-bits, lack of 2's complement, etc.). ## Fixed-width floating point types -Rust's `f32` and `f64` types have the same layout as C's `float` and `double` -types, respectively. Therefore these floating-point types are safe to use -directly in C FFI where the appropriate C types are expected. - -## Relationship to C integer hierarchy -C integers: -- char: at least 8 bits -- short: at least 16 bits (also at least a char) -- int: at least a short (intended to be a native integer size) -- long: at least 32 bits (also at least an int) -- long long: at least 64 bits (also at least a long) -The C integer types specify a minimum size, but not the exact size. For this reason, Rust integer types are not necessarily compatible with the “corresponding” C integer type. Instead, use the corresponding fixed size data types (e.g. `i64` in Rust would correspond to `int64_t` in C). - -## Controversies -There has been some debate about what to pick as the "official" behavior for bool: -* Rust does what C does (this is what the lang team decided) - * and in all cases you care about, that is 1 byte that is 0 or 1 -or -* Rust makes it 1 byte with values 0 or 1 - * and in all cases you care about, this is what C does - -Related discussions: [document the size of bool](https://github.com/rust-lang/rust/pull/46156), [bool== _Bool?](https://github.com/rust-rfcs/unsafe-code-guidelines/issues/53#issuecomment-447050232), [bool ABI](https://github.com/rust-lang/rust/pull/46176#issuecomment-359593446) - +Rust's `f32` and `f64` single (32-bit) and double (64-bit) precision +floating-point types have [IEEE-754] `binary32` and `binary64` floating-point +layouts, respectively. + +When the platforms' `"math.h"` header defines the `__STDC_IEC_559__` macro, +Rust's floating-point types are safe to use directly in C FFI where the +appropriate C types are expected (`f32` for `float`, `f64` for `double`). + +If the C platform's `"math.h"` header does not define the `__STDC_IEC_559__` +macro, whether using `f32` and `f64` in C FFI is safe or not for which C type is +_implementation-defined_. +> **Note**: the `libc` crate uses knowledge of each platform's +> _implementation-defined_ behavior to provide portable `libc::c_float` and +> `libc::c_double` types that can be used to safely interface with C via FFI. +[IEEE-754]: https://en.wikipedia.org/wiki/IEEE_754 From 8c550021bba99f20fa32ab8b84b882327a814b3f Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Fri, 15 Mar 2019 11:34:18 +0100 Subject: [PATCH 03/11] fixup --- reference/src/layout.md | 1 - reference/src/layout/integers-floatingpoint.md | 9 ++++++--- reference/src/optimizations.md | 1 - 3 files changed, 6 insertions(+), 5 deletions(-) delete mode 100644 reference/src/layout.md delete mode 100644 reference/src/optimizations.md diff --git a/reference/src/layout.md b/reference/src/layout.md deleted file mode 100644 index cb1f7674..00000000 --- a/reference/src/layout.md +++ /dev/null @@ -1 +0,0 @@ -# Data layout diff --git a/reference/src/layout/integers-floatingpoint.md b/reference/src/layout/integers-floatingpoint.md index bdd98348..4163d1f8 100644 --- a/reference/src/layout/integers-floatingpoint.md +++ b/reference/src/layout/integers-floatingpoint.md @@ -22,16 +22,19 @@ taking on the values 1 (`true`) or 0 (`false`). ## `char` -Rust char is 32-bit wide and represents [Unicode scalar value](http://www.unicode.org/glossary/#unicode_scalar_value). +Rust char is 32-bit wide and represents an [unicode scalar value]. The alignment +of `char` is _implementation-defined_. + +[unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value > **Note**: Rust `char` type is not layout compatible with C / C++ `char` types. > The C / C++ `char` types correspond to either Rust's `i8` or `u8` types on all > currently supported platforms, depending on their signedness. Rust does not > support C platforms in which C `char` is not 8-bit wide. -## `usize`/`isize` +## `isize` and `usize` -The `usize` and `isize` types are pointer-sized signed and unsigned integers. +The `isize` and `usize` types are pointer-sized signed and unsigned integers. They have the same layout as the [pointer types] for which the pointee is `Sized`, and are layout compatible with C's `uintptr_t` and `intptr_t` types. diff --git a/reference/src/optimizations.md b/reference/src/optimizations.md deleted file mode 100644 index b3d77f39..00000000 --- a/reference/src/optimizations.md +++ /dev/null @@ -1 +0,0 @@ -# Optimizations From 559d1a57ca30411dbba332828e2f773b86f502c4 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Fri, 15 Mar 2019 12:00:01 +0100 Subject: [PATCH 04/11] Fix mdbook; remove FIXMEs --- reference/src/SUMMARY.md | 4 +++- reference/src/layout/function-pointers.md | 10 ++++++---- reference/src/layout/pointers.md | 4 ++-- .../{integers-floatingpoint.md => scalar.md} | 17 ++--------------- 4 files changed, 13 insertions(+), 22 deletions(-) rename reference/src/layout/{integers-floatingpoint.md => scalar.md} (83%) diff --git a/reference/src/SUMMARY.md b/reference/src/SUMMARY.md index db593e02..7f3531c1 100644 --- a/reference/src/SUMMARY.md +++ b/reference/src/SUMMARY.md @@ -4,9 +4,11 @@ - [Data layout](./layout.md) - [Structs and tuples](./layout/structs-and-tuples.md) - - [Integers and Floating Points](./layout/integers-floatingpoint.md) + - [Scalar types](./layout/scalar.md) - [Enums](./layout/enums.md) - [Unions](./layout/unions.md) + - [Pointers](./layout/pointers.md) + - [Function pointers](./layout/function-pointers.md) - [Arrays and Slices](./layout/arrays-and-slices.md) - [Packed SIMD vectors](./layout/packed-simd-vectors.md) - [Optimizations](./optimizations.md) diff --git a/reference/src/layout/function-pointers.md b/reference/src/layout/function-pointers.md index 89785261..9869ebe9 100644 --- a/reference/src/layout/function-pointers.md +++ b/reference/src/layout/function-pointers.md @@ -81,6 +81,11 @@ bool for_all(struct Cons const *self, bool (*func)(int, void *), void *thunk); ``` ```rust +# use std::{ +# ffi::c_void, +# os::raw::c_int, +# }; +# pub struct Cons { data: c_int, next: Option>, @@ -117,9 +122,6 @@ pub extern "C" fn for_all( } it = node.next.as_ref().map(|x| &**x); } + true } ``` - -### Unresolved Questions - -- dunno diff --git a/reference/src/layout/pointers.md b/reference/src/layout/pointers.md index ef9abdb0..160ffbb3 100644 --- a/reference/src/layout/pointers.md +++ b/reference/src/layout/pointers.md @@ -36,7 +36,7 @@ multi-trait objects `&(dyn T + U)` or references to other dynamically sized type other than that they are at least word-aligned, and have size at least one word. The layout of `&dyn T` when `T` is a trait is the same as that of: -```rust +```rust,ignore #[repr(C)] struct DynObject { data: *u8, @@ -45,7 +45,7 @@ struct DynObject { ``` The layout of `&[T]` is the same as that of: -```rust +```rust,ignore #[repr(C)] struct Slice { ptr: *T, diff --git a/reference/src/layout/integers-floatingpoint.md b/reference/src/layout/scalar.md similarity index 83% rename from reference/src/layout/integers-floatingpoint.md rename to reference/src/layout/scalar.md index 4163d1f8..a6c1b188 100644 --- a/reference/src/layout/integers-floatingpoint.md +++ b/reference/src/layout/scalar.md @@ -1,8 +1,7 @@ -# Layout of Boolean, Floating Point, and Integral Types +# Layout of scalar types This chapter represents the consensus from issue [#9]. It documents the memory -layout and considerations for `bool`, floating point types (`f{32, 64}`), and -integral types (`{i,u}{8,16,32,64,128,size}`). +layout and considerations for `bool`, `char`, floating point types (`f{32, 64}`), and integral types (`{i,u}{8,16,32,64,128,size}`). These types are all scalar types, representing a single value, and have no layout `#[repr()]` flags. @@ -48,22 +47,10 @@ The layout of `usize` determines the following: - the maximum number of elements in an array (`[T; N: usize]`), - how much a pointer of a certain type can be offseted (limited by `usize::max_value()`). -> **FIXME**: Pointer `add` operates on `usize`, but pointer `offset` operates on -> `isize`, so unless by "offseted" we mean something different from `ptr.offset` -> above, `usize::max_value()` does not determine how much a pointer can be -> "offseted". We should probably be more specific here and call out `ptr.add` -> and `ptr.offset` explicitly. - The maximum size of any single value must fit within `usize` to [ensure that pointer diff is representable](https://github.com/rust-rfcs/unsafe-code-guidelines/pull/5#discussion_r212703192). -> **FIXME**: This does not make sense. We state that the layout of `usize` -> determines the maximum size of an object, and then argue that this is to -> ensure that pointer diff is representable, which won't be the case if the size -> of an object is `usize::max_val()`. The link cited actually states that, right -> now, the largest size of a Rust object is limited by `isize::max_value()`. - [pointer types]: ./pointers.md ## Fixed-width integer types From 46b71b78b21b2edf958b7ee6b87d14881b5224f3 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Fri, 15 Mar 2019 12:01:51 +0100 Subject: [PATCH 05/11] Rename scalar to scalars --- reference/src/SUMMARY.md | 2 +- reference/src/layout/{scalar.md => scalars.md} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename reference/src/layout/{scalar.md => scalars.md} (100%) diff --git a/reference/src/SUMMARY.md b/reference/src/SUMMARY.md index 7f3531c1..b3cc4129 100644 --- a/reference/src/SUMMARY.md +++ b/reference/src/SUMMARY.md @@ -4,7 +4,7 @@ - [Data layout](./layout.md) - [Structs and tuples](./layout/structs-and-tuples.md) - - [Scalar types](./layout/scalar.md) + - [Scalars](./layout/scalars.md) - [Enums](./layout/enums.md) - [Unions](./layout/unions.md) - [Pointers](./layout/pointers.md) diff --git a/reference/src/layout/scalar.md b/reference/src/layout/scalars.md similarity index 100% rename from reference/src/layout/scalar.md rename to reference/src/layout/scalars.md From b7320720ef834dd2634edf83720289632c0f78c8 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Fri, 15 Mar 2019 12:06:57 +0100 Subject: [PATCH 06/11] Language --- reference/src/layout/scalars.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/reference/src/layout/scalars.md b/reference/src/layout/scalars.md index a6c1b188..8a5adf66 100644 --- a/reference/src/layout/scalars.md +++ b/reference/src/layout/scalars.md @@ -68,18 +68,17 @@ C does not expose equivalent types in ``. Rust fixed-width integer types are therefore safe to use directly in C FFI where the corresponding C fixed-width integer types are expected. -integer types are expected. ### Layout compatibility with C native integer types The specification of native C integer types, `char`, `short`, `int`, `long`, -... as well as their `unsigned` variants, has a lower bound on their size, +... as well as their `unsigned` variants, guarantees a lower bound on their size, e.g., `short` is _at least_ 16-bit wide and _at least_ as wide as `char`. -Their actual exact sizes are _implementation-defined_. +Their exact sizes are _implementation-defined_. Libraries like `libc` use knowledge of this _implementation-defined_ behavior on each platform to select a layout-compatible Rust fixed-width integer type when -interfacing with native C integer types. +interfacing with native C integer types (e.g. `libc::c_int`). > **Note**: Rust does not support C platforms on which the C native integer type > are not compatible with any of Rust's fixed-width integer type (e.g. because From d8ca372e0eb585fe8ae9147ba8ea6aea2f7c67a9 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 16 Mar 2019 10:37:22 +0100 Subject: [PATCH 07/11] Fix usize limitations Closes #102 . --- reference/src/layout/scalars.md | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/reference/src/layout/scalars.md b/reference/src/layout/scalars.md index 8a5adf66..57ae0a02 100644 --- a/reference/src/layout/scalars.md +++ b/reference/src/layout/scalars.md @@ -41,15 +41,25 @@ They have the same layout as the [pointer types] for which the pointee is > `unsigned` is at least as large as a short, allowed to have padding bits, etc. > but it is not necessarily pointer-sized. -The layout of `usize` determines the following: - -- the maximum size of Rust objects (`size_of` and `size_of_val` return `usize`), -- the maximum number of elements in an array (`[T; N: usize]`), -- how much a pointer of a certain type can be offseted (limited by `usize::max_value()`). - -The maximum size of any single value must fit within `usize` to [ensure that -pointer diff is -representable](https://github.com/rust-rfcs/unsafe-code-guidelines/pull/5#discussion_r212703192). +The layout of `usize` determine the following: + +- the maximum size of Rust values is _implementation-defined_, but can at most + be `usize::max_value` since `mem::size_of` and `mem::size_of_val` return + `usize`, +- the maximum number of elements in an array is _implementation-defined_, but + can at most be `usize::max_value()` since `[T; N: usize]`, +- the maximum value by which a pointer can be offseted is + _implementation-defined_, but can at most be `usize::max_value()` since + `ptr.add(count: usize)`. + +> **Note**: in the current Rust implementation: +> +> * the maximum size of Rust values is limited to `isize::max_value()`. The LLVM +> `getelementptr` instruction uses signed-integer field offsets. Rust calls +> `getelementptr` with the `inbounds` flag which assumes that field offsets do +> not overflow, +> * the maximum number of elements in an array is `usize::max_value()`, +> * the maximum value by which a pointer can be offseted is `usize::max_value()`. [pointer types]: ./pointers.md @@ -74,6 +84,7 @@ the corresponding C fixed-width integer types are expected. The specification of native C integer types, `char`, `short`, `int`, `long`, ... as well as their `unsigned` variants, guarantees a lower bound on their size, e.g., `short` is _at least_ 16-bit wide and _at least_ as wide as `char`. + Their exact sizes are _implementation-defined_. Libraries like `libc` use knowledge of this _implementation-defined_ behavior on From a8f3ed16c77f4bf16e6394e61b150d4aaf832bee Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 16 Mar 2019 11:37:00 +0100 Subject: [PATCH 08/11] Remove the implementation-defined bit and pieces --- reference/src/layout/scalars.md | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/reference/src/layout/scalars.md b/reference/src/layout/scalars.md index 57ae0a02..6b471536 100644 --- a/reference/src/layout/scalars.md +++ b/reference/src/layout/scalars.md @@ -41,25 +41,20 @@ They have the same layout as the [pointer types] for which the pointee is > `unsigned` is at least as large as a short, allowed to have padding bits, etc. > but it is not necessarily pointer-sized. -The layout of `usize` determine the following: - -- the maximum size of Rust values is _implementation-defined_, but can at most - be `usize::max_value` since `mem::size_of` and `mem::size_of_val` return - `usize`, -- the maximum number of elements in an array is _implementation-defined_, but - can at most be `usize::max_value()` since `[T; N: usize]`, -- the maximum value by which a pointer can be offseted is - _implementation-defined_, but can at most be `usize::max_value()` since - `ptr.add(count: usize)`. - -> **Note**: in the current Rust implementation: +> **Note**: in the current Rust implementation, the layouts of `isize` and +> `usize` determine the following: > > * the maximum size of Rust values is limited to `isize::max_value()`. The LLVM > `getelementptr` instruction uses signed-integer field offsets. Rust calls > `getelementptr` with the `inbounds` flag which assumes that field offsets do > not overflow, -> * the maximum number of elements in an array is `usize::max_value()`, -> * the maximum value by which a pointer can be offseted is `usize::max_value()`. +> * the maximum number of elements in an array is `usize::max_value()` (`[T; N: +> usize]`), +> * the maximum value by which a pointer can be offseted using `ptr.add(count: +> usize)` is `usize::max_value()`. +> +> These limits have not gone through the RFC process and are not guaranteed to +> hold. [pointer types]: ./pointers.md From 712ca73aadb054ff286bc6b42bfb3792b4548c80 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 16 Mar 2019 11:59:30 +0100 Subject: [PATCH 09/11] note that usize::MAX arrays -> ZSTs --- reference/src/layout/scalars.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/reference/src/layout/scalars.md b/reference/src/layout/scalars.md index 6b471536..50076005 100644 --- a/reference/src/layout/scalars.md +++ b/reference/src/layout/scalars.md @@ -48,8 +48,11 @@ They have the same layout as the [pointer types] for which the pointee is > `getelementptr` instruction uses signed-integer field offsets. Rust calls > `getelementptr` with the `inbounds` flag which assumes that field offsets do > not overflow, +> > * the maximum number of elements in an array is `usize::max_value()` (`[T; N: -> usize]`), +> usize]`. Only ZST arrays can probably be this large in practice, non-ZST +> arrays are bound by the maximum size of Rust values, +> > * the maximum value by which a pointer can be offseted using `ptr.add(count: > usize)` is `usize::max_value()`. > From ac5fe2bff1b90d8fb2ad802a57da19bb85e327dc Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 16 Mar 2019 12:00:52 +0100 Subject: [PATCH 10/11] emphasize value --- reference/src/layout/scalars.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/src/layout/scalars.md b/reference/src/layout/scalars.md index 50076005..8a6ea3bd 100644 --- a/reference/src/layout/scalars.md +++ b/reference/src/layout/scalars.md @@ -44,7 +44,7 @@ They have the same layout as the [pointer types] for which the pointee is > **Note**: in the current Rust implementation, the layouts of `isize` and > `usize` determine the following: > -> * the maximum size of Rust values is limited to `isize::max_value()`. The LLVM +> * the maximum size of Rust _values_ is limited to `isize::max_value()`. The LLVM > `getelementptr` instruction uses signed-integer field offsets. Rust calls > `getelementptr` with the `inbounds` flag which assumes that field offsets do > not overflow, From 3c4fb0789a07962d4bbf1ea0345271938dd0d36a Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 11 Apr 2019 17:43:51 +0200 Subject: [PATCH 11/11] Replace values with allocations --- reference/src/layout/scalars.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/reference/src/layout/scalars.md b/reference/src/layout/scalars.md index 8a6ea3bd..17736de8 100644 --- a/reference/src/layout/scalars.md +++ b/reference/src/layout/scalars.md @@ -44,10 +44,10 @@ They have the same layout as the [pointer types] for which the pointee is > **Note**: in the current Rust implementation, the layouts of `isize` and > `usize` determine the following: > -> * the maximum size of Rust _values_ is limited to `isize::max_value()`. The LLVM -> `getelementptr` instruction uses signed-integer field offsets. Rust calls -> `getelementptr` with the `inbounds` flag which assumes that field offsets do -> not overflow, +> * the maximum size of Rust _allocations_ is limited to `isize::max_value()`. +> The LLVM `getelementptr` instruction uses signed-integer field offsets. Rust +> calls `getelementptr` with the `inbounds` flag which assumes that field +> offsets do not overflow, > > * the maximum number of elements in an array is `usize::max_value()` (`[T; N: > usize]`. Only ZST arrays can probably be this large in practice, non-ZST