1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
macro_rules! stack_only_docs {
    ($item:item) => {
        /// Types which contain no pointers or references and can thus live entirely
        /// on the stack.
        ///
        /// This trait is automatically implemented when the compiler determines
        /// it's appropriate.
        ///
        /// Note that this trait is *sealed*, i.e. you cannot implement it on your
        /// own custom types.
        ///
        /// Primitive types like [`u8`] and structs, tuples, and enums made only
        /// from them implement [`StackOnly`].
        ///
        /// In contrast, `&T`, `&mut T`, `*const T`, `*mut T`, and any type
        /// containing a reference or a pointer do *not* implement [`StackOnly`].
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use rust_cuda::safety::StackOnly;
        /// fn assert_stackonly(_x: impl StackOnly) {}
        /// ```
        /// ```rust
        /// # use rust_cuda::safety::StackOnly;
        /// # fn assert_stackonly(_x: impl StackOnly) {}
        /// assert_stackonly(42); // ok
        /// ```
        /// ```rust
        /// # use rust_cuda::safety::StackOnly;
        /// # fn assert_stackonly(_x: impl StackOnly) {}
        /// assert_stackonly([42; 42]); // ok
        /// ```
        /// ```rust,compile_fail
        /// # use alloc::vec;
        /// # use rust_cuda::safety::StackOnly;
        /// # fn assert_stackonly(_x: impl StackOnly) {}
        /// assert_stackonly(vec![42]); // error
        /// ```
        /// ```rust,compile_fail
        /// # use alloc::vec;
        /// # use rust_cuda::safety::StackOnly;
        /// # fn assert_stackonly(_x: impl StackOnly) {}
        /// assert_stackonly(&42); // error
        /// ```
        /// ```rust,compile_fail
        /// # use alloc::vec;
        /// # use rust_cuda::safety::StackOnly;
        /// # fn assert_stackonly(_x: impl StackOnly) {}
        /// # use crate::utils::shared::r#static::ThreadBlockShared;
        /// assert_stackonly(ThreadBlockShared::new_uninit()); // error
        /// ```
        /// ```rust,compile_fail
        /// # use alloc::vec;
        /// # use rust_cuda::safety::StackOnly;
        /// # fn assert_stackonly(_x: impl StackOnly) {}
        /// # use crate::utils::shared::slice::ThreadBlockSharedSlice;
        /// assert_stackonly(ThreadBlockSharedSlice::new_uninit_with_len(0)); // error
        /// ```
        $item
    };
}

#[cfg(not(doc))]
stack_only_docs! {
    pub trait StackOnly: sealed::StackOnly {}
}
#[cfg(doc)]
stack_only_docs! {
    pub use sealed::StackOnly;
}

#[cfg(not(doc))]
impl<T: sealed::StackOnly> StackOnly for T {}

mod sealed {
    pub auto trait StackOnly {}

    impl<T: ?Sized> !StackOnly for &T {}
    impl<T: ?Sized> !StackOnly for &mut T {}
    impl<T: ?Sized> !StackOnly for *const T {}
    impl<T: ?Sized> !StackOnly for *mut T {}

    impl<T> StackOnly for core::marker::PhantomData<T> {}
}