• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2020 Gilad Naaman, Ralf Jung
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 
21 /// `addr_of!`, or just ref-then-cast when that is not available.
22 #[cfg(raw_ref_macros)]
23 #[macro_export]
24 #[doc(hidden)]
25 macro_rules! _memoffset__addr_of {
26     ($path:expr) => {{
27         $crate::__priv::ptr::addr_of!($path)
28     }};
29 }
30 #[cfg(not(raw_ref_macros))]
31 #[macro_export]
32 #[doc(hidden)]
33 macro_rules! _memoffset__addr_of {
34     ($path:expr) => {{
35         // This is UB because we create an intermediate reference to uninitialized memory.
36         // Nothing we can do about that without `addr_of!` though.
37         &$path as *const _
38     }};
39 }
40 
41 /// Deref-coercion protection macro.
42 #[cfg(allow_clippy)]
43 #[macro_export]
44 #[doc(hidden)]
45 macro_rules! _memoffset__field_check {
46     ($type:path, $field:tt) => {
47         // Make sure the field actually exists. This line ensures that a
48         // compile-time error is generated if $field is accessed through a
49         // Deref impl.
50         #[allow(clippy::unneeded_field_pattern)]
51         let $type { $field: _, .. };
52     };
53 }
54 #[cfg(not(allow_clippy))]
55 #[macro_export]
56 #[doc(hidden)]
57 macro_rules! _memoffset__field_check {
58     ($type:path, $field:tt) => {
59         // Make sure the field actually exists. This line ensures that a
60         // compile-time error is generated if $field is accessed through a
61         // Deref impl.
62         let $type { $field: _, .. };
63     };
64 }
65 
66 /// Deref-coercion protection macro.
67 #[macro_export]
68 #[doc(hidden)]
69 macro_rules! _memoffset__field_check_tuple {
70     ($type:ty, $field:tt) => {
71         // Make sure the type argument is a tuple
72         let (_, ..): $type;
73     };
74 }
75 
76 /// Computes a const raw pointer to the given field of the given base pointer
77 /// to the given parent type.
78 ///
79 /// The `base` pointer *must not* be dangling, but it *may* point to
80 /// uninitialized memory.
81 #[macro_export(local_inner_macros)]
82 macro_rules! raw_field {
83     ($base:expr, $parent:path, $field:tt) => {{
84         _memoffset__field_check!($parent, $field);
85         let base = $base; // evaluate $base outside the `unsafe` block
86 
87         // Get the field address.
88         // Crucially, we know that this will not trigger a deref coercion because
89         // of the field check we did above.
90         #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
91         unsafe {
92             _memoffset__addr_of!((*(base as *const $parent)).$field)
93         }
94     }};
95 }
96 
97 /// Computes a const raw pointer to the given field of the given base pointer
98 /// to the given parent tuple typle.
99 ///
100 /// The `base` pointer *must not* be dangling, but it *may* point to
101 /// uninitialized memory.
102 #[cfg(tuple_ty)]
103 #[macro_export(local_inner_macros)]
104 macro_rules! raw_field_tuple {
105     ($base:expr, $parent:ty, $field:tt) => {{
106         _memoffset__field_check_tuple!($parent, $field);
107         let base = $base; // evaluate $base outside the `unsafe` block
108 
109         // Get the field address.
110         // Crucially, we know that this will not trigger a deref coercion because
111         // of the field check we did above.
112         #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
113         unsafe {
114             _memoffset__addr_of!((*(base as *const $parent)).$field)
115         }
116     }};
117 }
118