interprocess_traits/
lib.rs

1#![cfg_attr(feature="experimental-auto-traits", feature(optin_builtin_traits))]
2#![cfg_attr(not(feature="std"), no_std)]
3//! The interprocess-traits crate provides type traits to annotate types which have certain
4//! properties when used in a multiprocess environment.
5
6
7#[cfg(feature="std")]
8use std as core;
9
10use core::sync::atomic::*;
11use core::num::*;
12
13#[cfg(feature="experimental-auto-traits")]
14macro_rules! maybe_auto_trait {
15    ($doctext:literal pub unsafe trait $traitname:ident: $deps:ident {}) => {
16        // NB: no supertrait, built-in traits cannot have them!
17        #[doc=$doctext]
18        pub unsafe auto trait $traitname {}
19    }
20}
21
22#[cfg(not(feature="experimental-auto-traits"))]
23macro_rules! maybe_auto_trait {
24    ($doctext:literal pub unsafe trait $traitname:ident: $deps:ident {}) => {
25        #[doc=$doctext]
26        pub unsafe trait $traitname: $deps {}
27    }
28}
29
30maybe_auto_trait! {
31"Types which can be transferred across process boundary.
32
33An example of non-`ProcSend` type would be any type that contains pointers to values in \
34a process’ address space. Instead a `ProcSend` type would use indices which the \
35processes would know how to convert into their own address space.
36
37In general, for any type to implement `ProcSend`, it must be [`Send`], as threads \
38conceptually are the same as processes which share the same address space.
39
40Unlike [`Send`], `ProcSend` is not an auto-trait by default, because auto-traits are not stable. \
41Unless the `auto_traits` feature is enabled, it will be necessary to implement this \
42trait manually.
43
44Finally, currently `ProcSend` is only implemented for the built-in types which have \
45specified type layout and are ffi-safe. This is a conservative default as there is \
46no guarantee that the two interacting processes will be compiled with a same version \
47of Rust or are Rust at all."
48pub unsafe trait ProcSend: Send {}
49}
50
51maybe_auto_trait! {
52"Types for which it is safe to share references between processes.
53
54Much like [`ProcSend`] is a cross-process [`Send`], [`ProcSync`] is a cross-process [`Sync`].
55
56In general, for any type to implement `ProcSync`, it must be [`Sync`], as threads conceptually \
57are the same as processes which sahre the same address space.
58
59Unlike [`Sync`], `ProcSync` is not an auto-trait by default, because auto-traits are not stable. \
60Unless the `auto_traits` feature is enabled, it will be necessary to implement this \
61trait manually."
62pub unsafe trait ProcSync: Sync {}
63}
64
65macro_rules! implement_marker_for {
66    (unsafe impl $trait:ident for $($t:ty),*) => {
67        $(unsafe impl $trait for $t {})*
68    };
69    (unsafe impl !$trait:ident for $($t:ty),*) => {
70        $(unsafe impl !$trait for $t {})*
71    };
72}
73
74macro_rules! implement_marker_for_tuples {
75    (unsafe impl $trait:ident for) => { };
76    (unsafe impl $trait:ident for $hd:ident, $($tl:ident,)*) => {
77        unsafe impl<$hd: $trait, $($tl: $trait),*> $trait for ($hd, $($tl),*) {}
78        implement_marker_for_tuples! {
79            unsafe impl $trait for $($tl,)*
80        }
81    };
82}
83
84implement_marker_for! {
85    unsafe impl ProcSend for
86    u8, u16, u32, u64, u128, usize,
87    i8, i16, i32, i64, i128, isize,
88    f32, f64,
89    bool, char, str,
90    AtomicU8, AtomicU16, AtomicU32, AtomicU64, AtomicUsize,
91    AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize,
92    AtomicBool,
93    NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
94    NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,
95    core::ffi::c_void
96}
97
98implement_marker_for_tuples! {
99    unsafe impl ProcSend for
100    T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
101}
102
103unsafe impl<T: ProcSend> ProcSend for core::cell::RefCell<T> {}
104unsafe impl<T: ProcSend> ProcSend for core::cell::Cell<T> {}
105unsafe impl<T: ProcSend> ProcSend for core::cell::UnsafeCell<T> {}
106unsafe impl<T: ProcSend> ProcSend for core::mem::ManuallyDrop<T> {}
107
108#[cfg(feature="experimental-auto-traits")]
109impl<T> !ProcSend for *const T {}
110#[cfg(feature="experimental-auto-traits")]
111impl<T> !ProcSend for *mut T {}
112#[cfg(feature="experimental-auto-traits")]
113impl<T> !ProcSend for AtomicPtr<T> {}
114#[cfg(feature="experimental-auto-traits")]
115impl<T> !ProcSend for &T {}
116#[cfg(feature="experimental-auto-traits")]
117impl<T> !ProcSend for &mut T {}
118#[cfg(all(feature="experimental-auto-traits", feature="std"))]
119impl !ProcSend for std::net::TcpListener {}
120#[cfg(all(feature="experimental-auto-traits", feature="std"))]
121impl !ProcSend for std::net::TcpStream {}
122#[cfg(all(feature="experimental-auto-traits", feature="std"))]
123impl !ProcSend for std::net::UdpSocket {}
124#[cfg(all(feature="experimental-auto-traits", feature="std", unix))]
125impl !ProcSend for std::os::unix::net::UnixDatagram {}
126#[cfg(all(feature="experimental-auto-traits", feature="std", unix))]
127impl !ProcSend for std::os::unix::net::UnixListener {}
128#[cfg(all(feature="experimental-auto-traits", feature="std", unix))]
129impl !ProcSend for std::os::unix::net::UnixStream {}
130#[cfg(all(feature="experimental-auto-traits", feature="std"))]
131impl !ProcSend for std::fs::File {}
132#[cfg(all(feature="experimental-auto-traits", feature="std"))]
133impl !ProcSend for std::process::Child {}
134#[cfg(all(feature="experimental-auto-traits", feature="std"))]
135impl !ProcSend for std::process::ChildStderr {}
136#[cfg(all(feature="experimental-auto-traits", feature="std"))]
137impl !ProcSend for std::process::ChildStdin {}
138#[cfg(all(feature="experimental-auto-traits", feature="std"))]
139impl !ProcSend for std::process::ChildStdout {}
140#[cfg(all(feature="experimental-auto-traits", feature="std"))]
141impl !ProcSend for std::process::Stdio {}
142#[cfg(all(feature="experimental-auto-traits", feature="std"))]
143impl !ProcSend for std::thread::ThreadId {}
144
145
146implement_marker_for! {
147    unsafe impl ProcSync for
148    u8, u16, u32, u64, u128, usize,
149    i8, i16, i32, i64, i128, isize,
150    f32, f64,
151    bool, char, str,
152    AtomicU8, AtomicU16, AtomicU32, AtomicU64, AtomicUsize,
153    AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize,
154    AtomicBool,
155    NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
156    NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,
157    core::ffi::c_void
158}
159
160implement_marker_for_tuples! {
161    unsafe impl ProcSync for
162    T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
163}
164
165unsafe impl<T: ProcSync> ProcSync for core::mem::ManuallyDrop<T> {}
166
167#[cfg(feature="experimental-auto-traits")]
168impl<T> !ProcSync for core::cell::Cell<T> {}
169#[cfg(feature="experimental-auto-traits")]
170impl<T> !ProcSync for core::cell::UnsafeCell<T> {}
171#[cfg(feature="experimental-auto-traits")]
172impl<T> !ProcSync for *const T {}
173#[cfg(feature="experimental-auto-traits")]
174impl<T> !ProcSync for *mut T {}
175#[cfg(feature="experimental-auto-traits")]
176impl<T> !ProcSync for AtomicPtr<T> {}
177#[cfg(feature="experimental-auto-traits")]
178impl<T> !ProcSync for core::ptr::NonNull<T> {}
179#[cfg(feature="experimental-auto-traits")]
180impl<T> !ProcSync for &T {}
181#[cfg(feature="experimental-auto-traits")]
182impl<T> !ProcSync for &mut T {}
183#[cfg(all(feature="experimental-auto-traits", feature="std"))]
184impl !ProcSync for std::net::TcpListener {}
185#[cfg(all(feature="experimental-auto-traits", feature="std"))]
186impl !ProcSync for std::net::TcpStream {}
187#[cfg(all(feature="experimental-auto-traits", feature="std"))]
188impl !ProcSync for std::net::UdpSocket {}
189#[cfg(all(feature="experimental-auto-traits", feature="std", unix))]
190impl !ProcSync for std::os::unix::net::UnixDatagram {}
191#[cfg(all(feature="experimental-auto-traits", feature="std", unix))]
192impl !ProcSync for std::os::unix::net::UnixListener {}
193#[cfg(all(feature="experimental-auto-traits", feature="std", unix))]
194impl !ProcSync for std::os::unix::net::UnixStream {}
195#[cfg(all(feature="experimental-auto-traits", feature="std"))]
196impl !ProcSync for std::fs::File {}
197#[cfg(all(feature="experimental-auto-traits", feature="std"))]
198impl !ProcSync for std::process::Child {}
199#[cfg(all(feature="experimental-auto-traits", feature="std"))]
200impl !ProcSync for std::process::ChildStderr {}
201#[cfg(all(feature="experimental-auto-traits", feature="std"))]
202impl !ProcSync for std::process::ChildStdin {}
203#[cfg(all(feature="experimental-auto-traits", feature="std"))]
204impl !ProcSync for std::process::ChildStdout {}
205#[cfg(all(feature="experimental-auto-traits", feature="std"))]
206impl !ProcSync for std::process::Stdio {}
207#[cfg(all(feature="experimental-auto-traits", feature="std"))]
208impl !ProcSync for std::thread::ThreadId {}