Skip to content

Commit ed532cc

Browse files
committed
Put the RFC behind a feature gate result_ffi_guarantees
1 parent 437ca26 commit ed532cc

File tree

8 files changed

+499
-28
lines changed

8 files changed

+499
-28
lines changed

compiler/rustc_feature/src/unstable.rs

+3
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,9 @@ declare_features! (
585585
(incomplete, repr128, "1.16.0", Some(56071)),
586586
/// Allows `repr(simd)` and importing the various simd intrinsics.
587587
(unstable, repr_simd, "1.4.0", Some(27731)),
588+
/// Allows enums like Result<T, E> to be used across FFI, if T's niche value can
589+
/// be used to describe E or vise-versa.
590+
(unstable, result_ffi_guarantees, "CURRENT_RUSTC_VERSION", Some(110503)),
588591
/// Allows bounding the return type of AFIT/RPITIT.
589592
(incomplete, return_type_notation, "1.70.0", Some(109417)),
590593
/// 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
@@ -1509,6 +1509,7 @@ symbols! {
15091509
require,
15101510
residual,
15111511
result,
1512+
result_ffi_guarantees,
15121513
resume,
15131514
return_position_impl_trait_in_trait,
15141515
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,99 @@
1+
#![allow(dead_code)]
2+
#![deny(improper_ctypes)]
3+
#![feature(ptr_internals)]
4+
5+
use std::num;
6+
7+
enum Z {}
8+
9+
#[repr(transparent)]
10+
struct TransparentStruct<T>(T, std::marker::PhantomData<Z>);
11+
12+
#[repr(transparent)]
13+
enum TransparentEnum<T> {
14+
Variant(T, std::marker::PhantomData<Z>),
15+
}
16+
17+
struct NoField;
18+
19+
extern "C" {
20+
fn result_ref_t(x: Result<&'static u8, ()>);
21+
//~^ ERROR `extern` block uses type `Result
22+
fn result_fn_t(x: Result<extern "C" fn(), ()>);
23+
//~^ ERROR `extern` block uses type `Result
24+
fn result_nonnull_t(x: Result<std::ptr::NonNull<u8>, ()>);
25+
//~^ ERROR `extern` block uses type `Result
26+
fn result_unique_t(x: Result<std::ptr::Unique<u8>, ()>);
27+
//~^ ERROR `extern` block uses type `Result
28+
fn result_nonzero_u8_t(x: Result<num::NonZero<u8>, ()>);
29+
//~^ ERROR `extern` block uses type `Result
30+
fn result_nonzero_u16_t(x: Result<num::NonZero<u16>, ()>);
31+
//~^ ERROR `extern` block uses type `Result
32+
fn result_nonzero_u32_t(x: Result<num::NonZero<u32>, ()>);
33+
//~^ ERROR `extern` block uses type `Result
34+
fn result_nonzero_u64_t(x: Result<num::NonZero<u64>, ()>);
35+
//~^ ERROR `extern` block uses type `Result
36+
fn result_nonzero_usize_t(x: Result<num::NonZero<usize>, ()>);
37+
//~^ ERROR `extern` block uses type `Result
38+
fn result_nonzero_i8_t(x: Result<num::NonZero<i8>, ()>);
39+
//~^ ERROR `extern` block uses type `Result
40+
fn result_nonzero_i16_t(x: Result<num::NonZero<i16>, ()>);
41+
//~^ ERROR `extern` block uses type `Result
42+
fn result_nonzero_i32_t(x: Result<num::NonZero<i32>, ()>);
43+
//~^ ERROR `extern` block uses type `Result
44+
fn result_nonzero_i64_t(x: Result<num::NonZero<i64>, ()>);
45+
//~^ ERROR `extern` block uses type `Result
46+
fn result_nonzero_isize_t(x: Result<num::NonZero<isize>, ()>);
47+
//~^ ERROR `extern` block uses type `Result
48+
fn result_transparent_struct_t(x: Result<TransparentStruct<num::NonZero<u8>>, ()>);
49+
//~^ ERROR `extern` block uses type `Result
50+
fn result_transparent_enum_t(x: Result<TransparentEnum<num::NonZero<u8>>, ()>);
51+
//~^ ERROR `extern` block uses type `Result
52+
fn result_phantom_t(x: Result<num::NonZero<u8>, std::marker::PhantomData<()>>);
53+
//~^ ERROR `extern` block uses type `Result
54+
fn result_1zst_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, Z>);
55+
//~^ ERROR `extern` block uses type `Result
56+
fn result_1zst_exhaustive_no_field_t(x: Result<num::NonZero<u8>, NoField>);
57+
//~^ ERROR `extern` block uses type `Result
58+
59+
fn result_ref_e(x: Result<(), &'static u8>);
60+
//~^ ERROR `extern` block uses type `Result
61+
fn result_fn_e(x: Result<(), extern "C" fn()>);
62+
//~^ ERROR `extern` block uses type `Result
63+
fn result_nonnull_e(x: Result<(), std::ptr::NonNull<u8>>);
64+
//~^ ERROR `extern` block uses type `Result
65+
fn result_unique_e(x: Result<(), std::ptr::Unique<u8>>);
66+
//~^ ERROR `extern` block uses type `Result
67+
fn result_nonzero_u8_e(x: Result<(), num::NonZero<u8>>);
68+
//~^ ERROR `extern` block uses type `Result
69+
fn result_nonzero_u16_e(x: Result<(), num::NonZero<u16>>);
70+
//~^ ERROR `extern` block uses type `Result
71+
fn result_nonzero_u32_e(x: Result<(), num::NonZero<u32>>);
72+
//~^ ERROR `extern` block uses type `Result
73+
fn result_nonzero_u64_e(x: Result<(), num::NonZero<u64>>);
74+
//~^ ERROR `extern` block uses type `Result
75+
fn result_nonzero_usize_e(x: Result<(), num::NonZero<usize>>);
76+
//~^ ERROR `extern` block uses type `Result
77+
fn result_nonzero_i8_e(x: Result<(), num::NonZero<i8>>);
78+
//~^ ERROR `extern` block uses type `Result
79+
fn result_nonzero_i16_e(x: Result<(), num::NonZero<i16>>);
80+
//~^ ERROR `extern` block uses type `Result
81+
fn result_nonzero_i32_e(x: Result<(), num::NonZero<i32>>);
82+
//~^ ERROR `extern` block uses type `Result
83+
fn result_nonzero_i64_e(x: Result<(), num::NonZero<i64>>);
84+
//~^ ERROR `extern` block uses type `Result
85+
fn result_nonzero_isize_e(x: Result<(), num::NonZero<isize>>);
86+
//~^ ERROR `extern` block uses type `Result
87+
fn result_transparent_struct_e(x: Result<(), TransparentStruct<num::NonZero<u8>>>);
88+
//~^ ERROR `extern` block uses type `Result
89+
fn result_transparent_enum_e(x: Result<(), TransparentEnum<num::NonZero<u8>>>);
90+
//~^ ERROR `extern` block uses type `Result
91+
fn result_phantom_e(x: Result<num::NonZero<u8>, std::marker::PhantomData<()>>);
92+
//~^ ERROR `extern` block uses type `Result
93+
fn result_1zst_exhaustive_no_variant_e(x: Result<Z, num::NonZero<u8>>);
94+
//~^ ERROR `extern` block uses type `Result
95+
fn result_1zst_exhaustive_no_field_e(x: Result<NoField, num::NonZero<u8>>);
96+
//~^ ERROR `extern` block uses type `Result
97+
}
98+
99+
pub fn main() {}

0 commit comments

Comments
 (0)