Skip to content

Commit 4b5a891

Browse files
committed
rfc text
1 parent c0a2cef commit 4b5a891

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

text/0000-result_ffi_guarantees.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# RFC: result_ffi_guarantees
2+
3+
- Feature Name: `result_ffi_guarantees`
4+
- Start Date: 2023-02-15
5+
- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)
6+
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)
7+
8+
# Summary
9+
[summary]: #summary
10+
11+
This RFC gives specific layout and ABI guarantees when wrapping "non-zero" data types from `core` in `Option` or `Result`. This allows those data types to be used directly in FFI, in place of the primitive form of the data (eg: `Result<(), NonZeroI32>` instead of `i32`).
12+
13+
# Motivation
14+
[motivation]: #motivation
15+
16+
Rust often needs to interact with foreign code. However, foreign function type signatures don't normally support any of Rust's rich type system. Particular function inputs and outputs will simply use 0 (or null) as a sentinel value and the programmer has to remember when that's happening.
17+
18+
Though it's common for "raw bindings" crates to also have "high level wrapper" crates that go with them (eg: `windows-sys`/`windows`, or `sdl2-sys`/`sdl2`, etc), someone still has to write those wrapper crates which use the foreign functions directly. Allowing Rust programmers to use more detailed types with foreign functions makes their work easier.
19+
20+
# Guide-level explanation
21+
[guide-level-explanation]: #guide-level-explanation
22+
23+
I'm not sure how to write a "guide" portion of this that's any simpler than the "reference" portion, which is already quite short.
24+
25+
# Reference-level explanation
26+
[reference-level-explanation]: #reference-level-explanation
27+
28+
When either of these two `core` types:
29+
30+
* `Option<T>`
31+
* `Result<T, E>` where either `T` or `E` are a zero-sized type with alignment 1 (a "1-ZST").
32+
33+
Is combined with a non-zero or non-null type (see the chart), the combination has the same layout (size and alignment) and the same ABI as the primitive form of the data.
34+
35+
| Example combined Type | Primitive Type |
36+
|:-|:-|
37+
| `Result<NonNull<T>, ()>` | `*mut T` |
38+
| `Result<&T, ()>` | `&T` |
39+
| `Result<&mut T, ()>` | `&mut T` |
40+
| `Result<fn(), ()>` | `fn()` |
41+
| `Result<NonZeroI8, ()>` | `i8` |
42+
| `Result<NonZeroI16, ()>` | `i16` |
43+
| `Result<NonZeroI32, ()>` | `i32` |
44+
| `Result<NonZeroI64, ()>` | `i64` |
45+
| `Result<NonZeroI128, ()>` | `i128` |
46+
| `Result<NonZeroIsize, ()>` | `isize` |
47+
| `Result<NonZeroU8, ()>` | `u8` |
48+
| `Result<NonZeroU16, ()>` | `u16` |
49+
| `Result<NonZeroU32, ()>` | `u32` |
50+
| `Result<NonZeroU64, ()>` | `u64` |
51+
| `Result<NonZeroU128, ()>` | `u128` |
52+
| `Result<NonZeroUsize, ()>` | `usize` |
53+
54+
* While `fn()` is listed just once in the above table, this rule applies to all `fn` types (regardless of ABI, arguments, and return type).
55+
56+
# Drawbacks
57+
[drawbacks]: #drawbacks
58+
59+
* The compiler has less flexibility with respect to discriminant computation and pattern matching optimizations when a type is niche-optimized.
60+
61+
# Rationale and alternatives
62+
[rationale-and-alternatives]: #rationale-and-alternatives
63+
64+
It's always possible to *not* strengthen the guarantees of the language.
65+
66+
# Prior art
67+
[prior-art]: #prior-art
68+
69+
The compiler already suports `Option` being combined with specific non-zero types, this RFC mostly expands the list of guaranteed support.
70+
71+
# Unresolved questions
72+
[unresolved-questions]: #unresolved-questions
73+
74+
None at this time.
75+
76+
# Future possibilities
77+
[future-possibilities]: #future-possibilities
78+
79+
* This could be expanded to include [ControlFlow](https://doc.rust-lang.org/nightly/core/ops/enum.ControlFlow.html) and [Poll](https://doc.rust-lang.org/nightly/core/task/enum.Poll.html).
80+
* This could be extended to *all* similar enums in the future. However, without a way to opt-in to the special layout and ABI guarantees (eg: a trait or attribute) it becomes yet another semver hazard for library authors. The RFC is deliberately limited in scope to avoid bikesheding.

0 commit comments

Comments
 (0)