Skip to content

Commit 56c5435

Browse files
committed
Put the RFC behind a feature gate result_ffi_guarantees
1 parent f4989a1 commit 56c5435

File tree

8 files changed

+501
-29
lines changed

8 files changed

+501
-29
lines changed

compiler/rustc_feature/src/unstable.rs

+3
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,9 @@ declare_features! (
573573
(incomplete, repr128, "1.16.0", Some(56071)),
574574
/// Allows `repr(simd)` and importing the various simd intrinsics.
575575
(unstable, repr_simd, "1.4.0", Some(27731)),
576+
/// Allows enums like Result<T, E> to be used across FFI, if T's niche value can
577+
/// be used to describe E or vise-versa.
578+
(unstable, result_ffi_guarantees, "CURRENT_RUSTC_VERSION", Some(110503)),
576579
/// Allows bounding the return type of AFIT/RPITIT.
577580
(incomplete, return_type_notation, "1.70.0", Some(109417)),
578581
/// Allows `extern "rust-cold"`.

compiler/rustc_lint/src/types.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,10 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
11421142
[var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) {
11431143
([], [field]) | ([field], []) => field.ty(tcx, args),
11441144
([field1], [field2]) => {
1145+
if !tcx.features().result_ffi_guarantees {
1146+
return None;
1147+
}
1148+
11451149
let ty1 = field1.ty(tcx, args);
11461150
let ty2 = field2.ty(tcx, args);
11471151

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,7 @@ symbols! {
14891489
require,
14901490
residual,
14911491
result,
1492+
result_ffi_guarantees,
14921493
resume,
14931494
return_position_impl_trait_in_trait,
14941495
return_type_notation,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# `result_ffi_guarantees`
2+
3+
The tracking issue for this feature is: [#110503]
4+
5+
[#110503]: https://github.com/rust-lang/rust/issues/110503
6+
7+
------------------------
8+
9+
This feature adds the possibility of using `Result<T, E>` in FFI if T's niche
10+
value can be used to describe E or vise-versa.
11+
12+
See [RFC 3391] for more information.
13+
14+
[RFC 3391]: https://github.com/rust-lang/rfcs/blob/master/text/3391-result_ffi_guarantees.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#![allow(dead_code)]
2+
#![deny(improper_ctypes)]
3+
#![feature(generic_nonzero)]
4+
#![feature(ptr_internals)]
5+
6+
use std::num;
7+
8+
enum Z {}
9+
10+
#[repr(transparent)]
11+
struct TransparentStruct<T>(T, std::marker::PhantomData<Z>);
12+
13+
#[repr(transparent)]
14+
enum TransparentEnum<T> {
15+
Variant(T, std::marker::PhantomData<Z>),
16+
}
17+
18+
struct NoField;
19+
20+
extern "C" {
21+
fn result_ref_t(x: Result<&'static u8, ()>);
22+
//~^ ERROR `extern` block uses type `Result
23+
fn result_fn_t(x: Result<extern "C" fn(), ()>);
24+
//~^ ERROR `extern` block uses type `Result
25+
fn result_nonnull_t(x: Result<std::ptr::NonNull<u8>, ()>);
26+
//~^ ERROR `extern` block uses type `Result
27+
fn result_unique_t(x: Result<std::ptr::Unique<u8>, ()>);
28+
//~^ ERROR `extern` block uses type `Result
29+
fn result_nonzero_u8_t(x: Result<num::NonZero<u8>, ()>);
30+
//~^ ERROR `extern` block uses type `Result
31+
fn result_nonzero_u16_t(x: Result<num::NonZero<u16>, ()>);
32+
//~^ ERROR `extern` block uses type `Result
33+
fn result_nonzero_u32_t(x: Result<num::NonZero<u32>, ()>);
34+
//~^ ERROR `extern` block uses type `Result
35+
fn result_nonzero_u64_t(x: Result<num::NonZero<u64>, ()>);
36+
//~^ ERROR `extern` block uses type `Result
37+
fn result_nonzero_usize_t(x: Result<num::NonZero<usize>, ()>);
38+
//~^ ERROR `extern` block uses type `Result
39+
fn result_nonzero_i8_t(x: Result<num::NonZero<i8>, ()>);
40+
//~^ ERROR `extern` block uses type `Result
41+
fn result_nonzero_i16_t(x: Result<num::NonZero<i16>, ()>);
42+
//~^ ERROR `extern` block uses type `Result
43+
fn result_nonzero_i32_t(x: Result<num::NonZero<i32>, ()>);
44+
//~^ ERROR `extern` block uses type `Result
45+
fn result_nonzero_i64_t(x: Result<num::NonZero<i64>, ()>);
46+
//~^ ERROR `extern` block uses type `Result
47+
fn result_nonzero_isize_t(x: Result<num::NonZero<isize>, ()>);
48+
//~^ ERROR `extern` block uses type `Result
49+
fn result_transparent_struct_t(x: Result<TransparentStruct<num::NonZero<u8>>, ()>);
50+
//~^ ERROR `extern` block uses type `Result
51+
fn result_transparent_enum_t(x: Result<TransparentEnum<num::NonZero<u8>>, ()>);
52+
//~^ ERROR `extern` block uses type `Result
53+
fn result_phantom_t(x: Result<num::NonZero<u8>, std::marker::PhantomData<()>>);
54+
//~^ ERROR `extern` block uses type `Result
55+
fn result_1zst_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, Z>);
56+
//~^ ERROR `extern` block uses type `Result
57+
fn result_1zst_exhaustive_no_field_t(x: Result<num::NonZero<u8>, NoField>);
58+
//~^ ERROR `extern` block uses type `Result
59+
60+
fn result_ref_e(x: Result<(), &'static u8>);
61+
//~^ ERROR `extern` block uses type `Result
62+
fn result_fn_e(x: Result<(), extern "C" fn()>);
63+
//~^ ERROR `extern` block uses type `Result
64+
fn result_nonnull_e(x: Result<(), std::ptr::NonNull<u8>>);
65+
//~^ ERROR `extern` block uses type `Result
66+
fn result_unique_e(x: Result<(), std::ptr::Unique<u8>>);
67+
//~^ ERROR `extern` block uses type `Result
68+
fn result_nonzero_u8_e(x: Result<(), num::NonZero<u8>>);
69+
//~^ ERROR `extern` block uses type `Result
70+
fn result_nonzero_u16_e(x: Result<(), num::NonZero<u16>>);
71+
//~^ ERROR `extern` block uses type `Result
72+
fn result_nonzero_u32_e(x: Result<(), num::NonZero<u32>>);
73+
//~^ ERROR `extern` block uses type `Result
74+
fn result_nonzero_u64_e(x: Result<(), num::NonZero<u64>>);
75+
//~^ ERROR `extern` block uses type `Result
76+
fn result_nonzero_usize_e(x: Result<(), num::NonZero<usize>>);
77+
//~^ ERROR `extern` block uses type `Result
78+
fn result_nonzero_i8_e(x: Result<(), num::NonZero<i8>>);
79+
//~^ ERROR `extern` block uses type `Result
80+
fn result_nonzero_i16_e(x: Result<(), num::NonZero<i16>>);
81+
//~^ ERROR `extern` block uses type `Result
82+
fn result_nonzero_i32_e(x: Result<(), num::NonZero<i32>>);
83+
//~^ ERROR `extern` block uses type `Result
84+
fn result_nonzero_i64_e(x: Result<(), num::NonZero<i64>>);
85+
//~^ ERROR `extern` block uses type `Result
86+
fn result_nonzero_isize_e(x: Result<(), num::NonZero<isize>>);
87+
//~^ ERROR `extern` block uses type `Result
88+
fn result_transparent_struct_e(x: Result<(), TransparentStruct<num::NonZero<u8>>>);
89+
//~^ ERROR `extern` block uses type `Result
90+
fn result_transparent_enum_e(x: Result<(), TransparentEnum<num::NonZero<u8>>>);
91+
//~^ ERROR `extern` block uses type `Result
92+
fn result_phantom_e(x: Result<num::NonZero<u8>, std::marker::PhantomData<()>>);
93+
//~^ ERROR `extern` block uses type `Result
94+
fn result_1zst_exhaustive_no_variant_e(x: Result<Z, num::NonZero<u8>>);
95+
//~^ ERROR `extern` block uses type `Result
96+
fn result_1zst_exhaustive_no_field_e(x: Result<NoField, num::NonZero<u8>>);
97+
//~^ ERROR `extern` block uses type `Result
98+
}
99+
100+
pub fn main() {}

0 commit comments

Comments
 (0)