Compare commits

...

15 Commits

Author SHA1 Message Date
Léo Lanteri Thauvin c700ad1802
Merge d00e6bbf51 into 5854fcc286 2024-04-27 08:26:02 -07:00
Eric Huss 5854fcc286
Merge pull request #1420 from daxpedda/wasm-target-feature-phase-4-5
Stabilize Wasm target features that are in phase 4 and 5
2024-04-21 13:47:07 +00:00
Eric Huss 5e68de3dc2
Merge pull request #1493 from kpreid/patch-1
Expand and clarify primitive alignment
2024-04-20 14:05:08 +00:00
Eric Huss 735c5dbf05
Merge pull request #1492 from conradludgate/patch-1
Update clone reference to include closures
2024-04-17 15:06:26 +00:00
Eric Huss 330ef95694
Clone: Also mention closures that don't capture anything 2024-04-17 08:04:47 -07:00
Kevin Reid a432cf4afd
Expand and clarify primitive alignment
These changes are intended to make the section more informative and readable, without making any new normative claims.

* Specify that the alignment might be _less_ than the size, rather than just that it might be different. This is mandatory and stated in the previous section, but I think it's useful to reiterate here.
* Mention `u128`/`i128` as another example of alignment less than size, so that this doesn't sound like a mainly 32-bit thing.
* Add `usize`/`isize` to the size table, so it can be spotted at a glance.
2024-04-16 09:35:51 -07:00
Conrad Ludgate 4f47e3ffe7
Update clone reference to include closures 2024-04-16 06:55:59 +01:00
Eric Huss 585b9bcb72
Merge pull request #1491 from kpreid/neunit
Document how `non_exhaustive` interacts with tuple and unit-like structs.
2024-04-15 19:59:53 +00:00
Kevin Reid 076a798583 Replace “min()” visibility notation with English. 2024-04-15 11:13:52 -07:00
Eric Huss a60221ad9c
Merge pull request #1490 from jlokier/patch-1
Fix link to RISC-V Zkt spec; it was pointing to Zkr
2024-04-15 16:12:40 +00:00
Kevin Reid ec0065fd92 Document how `non_exhaustive` interacts with tuple and unit-like structs. 2024-04-14 10:48:46 -07:00
Jamie Lokier b4311de691
Fix link to RISC-V Zkt spec; it was pointing to Zkr 2024-04-14 14:07:07 +01:00
daxpedda d035af92a1
Stabilize Wasm target features that are in phase 4 and 5 2023-11-01 00:19:00 +01:00
LeSeulArtichaut d00e6bbf51 Address review comments 2023-03-02 08:20:09 +01:00
LeSeulArtichaut 54107ec994 Document the `target_feature_11` feature 2022-03-17 23:09:54 +01:00
4 changed files with 132 additions and 37 deletions

View File

@ -55,7 +55,7 @@ features. It uses the [_MetaListNameValueStr_] syntax with a single key of
```rust
# #[cfg(target_feature = "avx2")]
#[target_feature(enable = "avx2")]
unsafe fn foo_avx2() {}
fn foo_avx2() {}
```
Each [target architecture] has a set of features that may be enabled. It is an
@ -66,9 +66,61 @@ It is [undefined behavior] to call a function that is compiled with a feature
that is not supported on the current platform the code is running on, *except*
if the platform explicitly documents this to be safe.
Functions marked with `target_feature` are not inlined into a context that
does not support the given features. The `#[inline(always)]` attribute may not
be used with a `target_feature` attribute.
For this reason, a function marked with `target_feature` is unsafe to call,
except inside a function that has at least the exact same `target_feature`
enabled. For example:
```rust
# #[cfg(target_feature = "avx2")] {
#[target_feature(enable = "avx")]
fn foo_avx() {}
fn bar() {
// Calling `foo_avx` here is unsafe, as we must ensure that AVX is
// available first, even if `avx` is enabled by default on the target
// platform or manually enabled as compiler flags.
unsafe {
foo_avx();
}
}
#[target_feature(enable = "avx")]
fn bar_avx() {
// Calling `foo_avx` here is safe.
foo_avx();
|| foo_avx();
}
#[target_feature(enable = "avx2")]
fn bar_avx2() {
// Calling `foo_avx` here is unsafe because `bar_avx2` doesn't enable `avx`
// specifically, even though in practice `avx2` implies `avx`.
unsafe {
foo_avx();
}
}
# }
```
Like unsafe functions, functions marked with `target_feature` cannot be
assigned to a safe function pointer and do not implement `FnOnce`. They can
however be assigned to unsafe function pointers:
```rust
# #[cfg(target_feature = "avx2")] {
# #[target_feature(enable = "avx2")]
# fn foo_avx2() {}
// `unsafe` is required here.
static MY_FN_PTR: unsafe fn () -> () = foo_avx2;
# }
```
`#[target_feature]` may not be applied to safe trait method implementations.
Functions marked with `target_feature` are not inlined into a context unless
it supports the given features. The `#[inline(always)]` attribute may not
be used with `target_feature`.
### Available features
@ -76,10 +128,6 @@ The following is a list of the available feature names.
#### `x86` or `x86_64`
Executing code with unsupported features is undefined behavior on this platform.
Hence this platform requires that `#[target_feature]` is only applied to [`unsafe`
functions][unsafe function].
Feature | Implicitly Enables | Description
------------|--------------------|-------------------
`adx` | | [ADX] — Multi-Precision Add-Carry Instruction Extensions
@ -143,9 +191,6 @@ Feature | Implicitly Enables | Description
#### `aarch64`
This platform requires that `#[target_feature]` is only applied to [`unsafe`
functions][unsafe function].
Further documentation on these features can be found in the [ARM Architecture
Reference Manual], or elsewhere on [developer.arm.com].
@ -262,21 +307,30 @@ Feature | Implicitly Enables | Description
[rv-zks]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zks.adoc
[rv-zksed]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zksed.adoc
[rv-zksh]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zksh.adoc
[rv-zkt]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zkr.adoc
[rv-zkt]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zkt.adoc
#### `wasm32` or `wasm64`
`#[target_feature]` may be used with both safe and
[`unsafe` functions][unsafe function] on Wasm platforms. It is impossible to
cause undefined behavior via the `#[target_feature]` attribute because
`#[target_feature]` may be called from a safe context on Wasm platforms. It is
impossible to cause undefined behavior via the `#[target_feature]` attribute because
attempting to use instructions unsupported by the Wasm engine will fail at load
time without the risk of being interpreted in a way different from what the
compiler expected.
Feature | Description
------------|-------------------
`simd128` | [WebAssembly simd proposal][simd128]
Feature | Description
----------------------|-------------------
`bulk-memory` | [WebAssembly bulk memory operations proposal][bulk-memory]
`extended-const` | [WebAssembly extended const expressions proposal][extended-const]
`mutable-globals` | [WebAssembly mutable global proposal][mutable-globals]
`nontrapping-fptoint` | [WebAssembly non-trapping float-to-int conversion proposal][nontrapping-fptoint]
`sign-ext` | [WebAssembly sign extension operators Proposal][sign-ext]
`simd128` | [WebAssembly simd proposal][simd128]
[bulk-memory]: https://github.com/WebAssembly/bulk-memory-operations
[extended-const]: https://github.com/WebAssembly/extended-const
[mutable-globals]: https://github.com/WebAssembly/mutable-global
[nontrapping-fptoint]: https://github.com/WebAssembly/nontrapping-float-to-int-conversions
[sign-ext]: https://github.com/WebAssembly/sign-extension-ops
[simd128]: https://github.com/webassembly/simd
### Additional information

View File

@ -20,6 +20,12 @@ pub struct Config {
pub window_height: u16,
}
#[non_exhaustive]
pub struct Token;
#[non_exhaustive]
pub struct Id(pub u64);
#[non_exhaustive]
pub enum Error {
Message(String),
@ -34,11 +40,13 @@ pub enum Message {
// Non-exhaustive structs can be constructed as normal within the defining crate.
let config = Config { window_width: 640, window_height: 480 };
let token = Token;
let id = Id(4);
// Non-exhaustive structs can be matched on exhaustively within the defining crate.
if let Config { window_width, window_height } = config {
// ...
}
let Config { window_width, window_height } = config;
let Token = token;
let Id(id_number) = id;
let error = Error::Other;
let message = Message::Reaction(3);
@ -64,30 +72,49 @@ Non-exhaustive types cannot be constructed outside of the defining crate:
- Non-exhaustive variants ([`struct`][struct] or [`enum` variant][enum]) cannot be constructed
with a [_StructExpression_] \(including with [functional update syntax]).
- The implicitly defined same-named constant of a [unit-like struct][struct],
or the same-named constructor function of a [tuple struct][struct],
has a [visibility] no greater than `pub(crate)`.
That is, if the structs visibility is `pub`, then the constant or constructors visibility
is `pub(crate)`, and otherwise the visibility of the two items is the same
(as is the case without `#[non_exhaustive]`).
- [`enum`][enum] instances can be constructed.
The following examples of construction do not compile when outside the defining crate:
<!-- ignore: requires external crates -->
```rust,ignore
// `Config`, `Error`, and `Message` are types defined in an upstream crate that have been
// annotated as `#[non_exhaustive]`.
use upstream::{Config, Error, Message};
// These are types defined in an upstream crate that have been annotated as
// `#[non_exhaustive]`.
use upstream::{Config, Token, Id, Error, Message};
// Cannot construct an instance of `Config`, if new fields were added in
// Cannot construct an instance of `Config`; if new fields were added in
// a new version of `upstream` then this would fail to compile, so it is
// disallowed.
let config = Config { window_width: 640, window_height: 480 };
// Can construct an instance of `Error`, new variants being introduced would
// Cannot construct an instance of `Token`; if new fields were added, then
// it would not be a unit-like struct any more, so the same-named constant
// created by it being a unit-like struct is not public outside the crate;
// this code fails to compile.
let token = Token;
// Cannot construct an instance of `Id`; if new fields were added, then
// its constructor function signature would change, so its constructor
// function is not public outside the crate; this code fails to compile.
let id = Id(5);
// Can construct an instance of `Error`; new variants being introduced would
// not result in this failing to compile.
let error = Error::Message("foo".to_string());
// Cannot construct an instance of `Message::Send` or `Message::Reaction`,
// Cannot construct an instance of `Message::Send` or `Message::Reaction`;
// if new fields were added in a new version of `upstream` then this would
// fail to compile, so it is disallowed.
let message = Message::Send { from: 0, to: 1, contents: "foo".to_string(), };
let message = Message::Reaction(0);
// Cannot construct an instance of `Message::Quit`, if this were converted to
// Cannot construct an instance of `Message::Quit`; if this were converted to
// a tuple-variant `upstream` then this would fail to compile.
let message = Message::Quit;
```
@ -95,16 +122,18 @@ let message = Message::Quit;
There are limitations when matching on non-exhaustive types outside of the defining crate:
- When pattern matching on a non-exhaustive variant ([`struct`][struct] or [`enum` variant][enum]),
a [_StructPattern_] must be used which must include a `..`. Tuple variant constructor visibility
is lowered to `min($vis, pub(crate))`.
a [_StructPattern_] must be used which must include a `..`. A tuple variant's constructor's
[visibility] is reduced to be no greater than `pub(crate)`.
- When pattern matching on a non-exhaustive [`enum`][enum], matching on a variant does not
contribute towards the exhaustiveness of the arms.
The following examples of matching do not compile when outside the defining crate:
<!-- ignore: requires external crates -->
```rust, ignore
// `Config`, `Error`, and `Message` are types defined in an upstream crate that have been
// annotated as `#[non_exhaustive]`.
use upstream::{Config, Error, Message};
// These are types defined in an upstream crate that have been annotated as
// `#[non_exhaustive]`.
use upstream::{Config, Token, Id, Error, Message};
// Cannot match on a non-exhaustive enum without including a wildcard arm.
match error {
@ -118,6 +147,13 @@ if let Ok(Config { window_width, window_height }) = config {
// would compile with: `..`
}
// Cannot match a non-exhaustive unit-like or tuple struct except by using
// braced struct syntax with a wildcard.
// This would compile as `let Token { .. } = token;`
let Token = token;
// This would compile as `let Id { 0: id_number, .. } = id;`
let Id(id_number) = id;
match message {
// Cannot match on a non-exhaustive struct enum variant without including a wildcard.
Message::Send { from, to, contents } => { },
@ -147,3 +183,4 @@ Non-exhaustive types are always considered inhabited in downstream crates.
[enum]: ../items/enumerations.md
[functional update syntax]: ../expressions/struct-expr.md#functional-update-syntax
[struct]: ../items/structs.md
[visibility]: ../visibility-and-privacy.md

View File

@ -80,6 +80,7 @@ types:
* Types with a built-in `Copy` implementation (see above)
* [Tuples] of `Clone` types
* [Closures] that only capture values of `Clone` types or capture no values from the environment
## `Send`

View File

@ -44,17 +44,20 @@ The size of most primitives is given in this table.
| `u32` / `i32` | 4 |
| `u64` / `i64` | 8 |
| `u128` / `i128` | 16 |
| `usize` / `isize` | See below |
| `f32` | 4 |
| `f64` | 8 |
| `char` | 4 |
`usize` and `isize` have a size big enough to contain every address on the
target platform. For example, on a 32 bit target, this is 4 bytes and on a 64
target platform. For example, on a 32 bit target, this is 4 bytes, and on a 64
bit target, this is 8 bytes.
Most primitives are generally aligned to their size, although this is
platform-specific behavior. In particular, on many 32-bit platforms `u64`
and `f64` are only aligned to 32 bits.
The alignment of primitives is platform-specific.
In most cases, their alignment is equal to their size, but it may be less.
In particular, `i128` and `u128` are often aligned to 4 or 8 bytes even though
their size is 16, and on many 32-bit platforms, `i64`, `u64`, and `f64` are only
aligned to 4 bytes, not 8.
## Pointers and References Layout