Auto merge of #27556 - taliesinb:tarpl-clarity-2, r=Gankro
* Some clarifying rephrasing. * Rename B.x back to B.a. * Make null pointer optimization section bit more concrete. r? @Gankro
This commit is contained in:
commit
fb92de75c1
@ -36,9 +36,9 @@ struct A {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
will be 32-bit aligned assuming these primitives are aligned to their size.
|
will be 32-bit aligned on an architecture that aligns these primitives to their
|
||||||
It will therefore have a size that is a multiple of 32-bits. It will potentially
|
respective sizes. The whole struct will therefore have a size that is a multiple
|
||||||
*really* become:
|
of 32-bits. It will potentially become:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
struct A {
|
struct A {
|
||||||
@ -50,10 +50,10 @@ struct A {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
There is *no indirection* for these types; all data is stored contiguously as
|
There is *no indirection* for these types; all data is stored within the struct,
|
||||||
you would expect in C. However with the exception of arrays (which are densely
|
as you would expect in C. However with the exception of arrays (which are
|
||||||
packed and in-order), the layout of data is not by default specified in Rust.
|
densely packed and in-order), the layout of data is not by default specified in
|
||||||
Given the two following struct definitions:
|
Rust. Given the two following struct definitions:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
struct A {
|
struct A {
|
||||||
@ -62,18 +62,17 @@ struct A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct B {
|
struct B {
|
||||||
x: i32,
|
a: i32,
|
||||||
b: u64,
|
b: u64,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Rust *does* guarantee that two instances of A have their data laid out in
|
Rust *does* guarantee that two instances of A have their data laid out in
|
||||||
exactly the same way. However Rust *does not* guarantee that an instance of A
|
exactly the same way. However Rust *does not* currently guarantee that an
|
||||||
has the same field ordering or padding as an instance of B (in practice there's
|
instance of A has the same field ordering or padding as an instance of B, though
|
||||||
no particular reason why they wouldn't, other than that its not currently
|
in practice there's no reason why they wouldn't.
|
||||||
guaranteed).
|
|
||||||
|
|
||||||
With A and B as written, this is basically nonsensical, but several other
|
With A and B as written, this point would seem to be pedantic, but several other
|
||||||
features of Rust make it desirable for the language to play with data layout in
|
features of Rust make it desirable for the language to play with data layout in
|
||||||
complex ways.
|
complex ways.
|
||||||
|
|
||||||
@ -133,18 +132,21 @@ struct FooRepr {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
And indeed this is approximately how it would be laid out in general
|
And indeed this is approximately how it would be laid out in general (modulo the
|
||||||
(modulo the size and position of `tag`). However there are several cases where
|
size and position of `tag`).
|
||||||
such a representation is inefficient. The classic case of this is Rust's
|
|
||||||
"null pointer optimization". Given a pointer that is known to not be null
|
|
||||||
(e.g. `&u32`), an enum can *store* a discriminant bit *inside* the pointer
|
|
||||||
by using null as a special value. The net result is that
|
|
||||||
`size_of::<Option<&T>>() == size_of::<&T>()`
|
|
||||||
|
|
||||||
There are many types in Rust that are, or contain, "not null" pointers such as
|
However there are several cases where such a representation is inefficient. The
|
||||||
|
classic case of this is Rust's "null pointer optimization": an enum consisting
|
||||||
|
of a single outer unit variant (e.g. `None`) and a (potentially nested) non-
|
||||||
|
nullable pointer variant (e.g. `&T`) makes the tag unnecessary, because a null
|
||||||
|
pointer value can safely be interpreted to mean that the unit variant is chosen
|
||||||
|
instead. The net result is that, for example, `size_of::<Option<&T>>() ==
|
||||||
|
size_of::<&T>()`.
|
||||||
|
|
||||||
|
There are many types in Rust that are, or contain, non-nullable pointers such as
|
||||||
`Box<T>`, `Vec<T>`, `String`, `&T`, and `&mut T`. Similarly, one can imagine
|
`Box<T>`, `Vec<T>`, `String`, `&T`, and `&mut T`. Similarly, one can imagine
|
||||||
nested enums pooling their tags into a single discriminant, as they are by
|
nested enums pooling their tags into a single discriminant, as they are by
|
||||||
definition known to have a limited range of valid values. In principle enums can
|
definition known to have a limited range of valid values. In principle enums could
|
||||||
use fairly elaborate algorithms to cache bits throughout nested types with
|
use fairly elaborate algorithms to cache bits throughout nested types with
|
||||||
special constrained representations. As such it is *especially* desirable that
|
special constrained representations. As such it is *especially* desirable that
|
||||||
we leave enum layout unspecified today.
|
we leave enum layout unspecified today.
|
||||||
|
Loading…
Reference in New Issue
Block a user