]> git.proxmox.com Git - rustc.git/blobdiff - vendor/memoffset/src/span_of.rs
New upstream version 1.38.0+dfsg1
[rustc.git] / vendor / memoffset / src / span_of.rs
index fcb49ed1974776aab428f866222a8b423d2e01d9..c48a4569b495c56363056e56102b4d67807fdf94 100644 (file)
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 // SOFTWARE.
 
+/// Reexport for `local_inner_macros`; see
+/// <https://doc.rust-lang.org/edition-guide/rust-2018/macros/macro-changes.html#macros-using-local_inner_macros>.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! _memoffset__compile_error {
+    ($($inner:tt)*) => {
+        compile_error! { $($inner)* }
+    }
+}
+
 /// Produces a range instance representing the sub-slice containing the specified member.
 ///
 /// This macro provides 2 forms of differing functionalities.
 ///
-/// The first form is identical to the appearance of the `offset_of!` macro,
-/// and just like `offset_of!`, it has no limit on the depth of fields / subscripts used.
+/// The first form is identical to the appearance of the `offset_of!` macro.
 ///
 /// ```ignore
-/// span_of!(Struct, member[index].field)
+/// span_of!(Struct, member)
 /// ```
 ///
 /// The second form of `span_of!` returns a sub-slice which starts at one field, and ends at another.
 /// span_of!(Struct, start ..)
 /// ```
 ///
-/// *Note*: 
-/// This macro uses recursion in order to resolve the range expressions, so there is a limit to the complexity of the expression.
+/// *Note*:
+/// This macro uses recursion in order to resolve the range expressions, so there is a limit to
+/// the complexity of the expression.
 /// In order to raise the limit, the compiler's recursion limit should be lifted.
 ///
-/// *Note*: 
-/// This macro may not make much sense when used on structs that are not `#[repr(C, packed)]`
-///
 /// ## Examples
 /// ```
 /// #[macro_use]
 /// extern crate memoffset;
 ///
-/// #[repr(C, packed)]
+/// #[repr(C)]
 /// struct Florp {
 ///     a: u32
 /// }
 ///
-/// #[repr(C, packed)]
+/// #[repr(C)]
 /// struct Blarg {
-///     x: u64,
+///     x: [u32; 2],
 ///     y: [u8; 56],
 ///     z: Florp,
 ///     egg: [[u8; 4]; 4]
 /// }
 ///
 /// fn main() {
+///     assert_eq!(0..84,  span_of!(Blarg, ..));
+///     assert_eq!(0..8,   span_of!(Blarg, .. y));
+///     assert_eq!(0..64,  span_of!(Blarg, ..= y));
 ///     assert_eq!(0..8,   span_of!(Blarg, x));
-///     assert_eq!(64..68, span_of!(Blarg, z.a));
-///     assert_eq!(79..80, span_of!(Blarg, egg[2][3]));
-///
-///     assert_eq!(8..64,  span_of!(Blarg, y[0]  ..  z));
-///     assert_eq!(0..42,  span_of!(Blarg, x     ..  y[34]));
-///     assert_eq!(0..64,  span_of!(Blarg, x     ..= y));
-///     assert_eq!(58..68, span_of!(Blarg, y[50] ..= z));
+///     assert_eq!(8..84,  span_of!(Blarg, y ..));
+///     assert_eq!(0..8,   span_of!(Blarg, x .. y));
+///     assert_eq!(0..64,  span_of!(Blarg, x ..= y));
 /// }
 /// ```
-#[macro_export]
+#[macro_export(local_inner_macros)]
 macro_rules! span_of {
-    (@helper $root:ident, [] ..=) => {
-        compile_error!("Expected a range, found '..='")
+    (@helper  $root:ident, [] ..=) => {
+        _memoffset__compile_error!("Expected a range, found '..='")
     };
     (@helper $root:ident, [] ..) => {
-        compile_error!("Expected a range, found '..'")
+        _memoffset__compile_error!("Expected a range, found '..'")
     };
-    (@helper $root:ident, [] ..= $($field:tt)+) => {
-        (&$root as *const _ as usize,
-         &$root.$($field)* as *const _ as usize + $crate::mem::size_of_val(&$root.$($field)*))
-    };
-    (@helper $root:ident, [] .. $($field:tt)+) => {
-        (&$root as *const _ as usize, &$root.$($field)* as *const _ as usize)
-    };
-    (@helper $root:ident, $(# $begin:tt)+ [] ..= $($end:tt)+) => {
-        (&$root.$($begin)* as *const _ as usize,
-         &$root.$($end)* as *const _ as usize + $crate::mem::size_of_val(&$root.$($end)*))
-    };
-    (@helper $root:ident, $(# $begin:tt)+ [] .. $($end:tt)+) => {
-        (&$root.$($begin)* as *const _ as usize, &$root.$($end)* as *const _ as usize)
-    };
-    (@helper $root:ident, $(# $begin:tt)+ [] ..) => {
-        (&$root.$($begin)* as *const _ as usize,
-         &$root as *const _ as usize + $crate::mem::size_of_val(&$root))
-    };
-    (@helper $root:ident, $(# $begin:tt)+ [] ..=) => {
-        compile_error!(
+    // Lots of UB due to taking references to uninitialized fields! But that can currently
+    // not be avoided.
+    // No explicit begin for range.
+    (@helper $root:ident, $parent:tt, [] ..) => {{
+        ($root as usize,
+         $root as usize + $crate::mem::size_of_val(&(*$root)))
+    }};
+    (@helper $root:ident, $parent:tt, [] ..= $field:tt) => {{
+        _memoffset__field_check!($parent, $field);
+        ($root as usize,
+         &(*$root).$field as *const _ as usize + $crate::mem::size_of_val(&(*$root).$field))
+    }};
+    (@helper $root:ident, $parent:tt, [] .. $field:tt) => {{
+        _memoffset__field_check!($parent, $field);
+        ($root as usize, &(*$root).$field as *const _ as usize)
+    }};
+    // Explicit begin and end for range.
+    (@helper $root:ident, $parent:tt, # $begin:tt [] ..= $end:tt) => {{
+        _memoffset__field_check!($parent, $begin);
+        _memoffset__field_check!($parent, $end);
+        (&(*$root).$begin as *const _ as usize,
+         &(*$root).$end as *const _ as usize + $crate::mem::size_of_val(&(*$root).$end))
+    }};
+    (@helper $root:ident, $parent:tt, # $begin:tt [] .. $end:tt) => {{
+        _memoffset__field_check!($parent, $begin);
+        _memoffset__field_check!($parent, $end);
+        (&(*$root).$begin as *const _ as usize,
+         &(*$root).$end as *const _ as usize)
+    }};
+    // No explicit end for range.
+    (@helper $root:ident, $parent:tt, # $begin:tt [] ..) => {{
+        _memoffset__field_check!($parent, $begin);
+        (&(*$root).$begin as *const _ as usize,
+         $root as usize + $crate::mem::size_of_val(&*$root))
+    }};
+    (@helper $root:ident, $parent:tt, # $begin:tt [] ..=) => {{
+        _memoffset__compile_error!(
             "Found inclusive range to the end of a struct. Did you mean '..' instead of '..='?")
-    };
-    (@helper $root:ident, $(# $begin:tt)+ []) => {
-        (&$root.$($begin)* as *const _ as usize,
-         &$root.$($begin)* as *const _ as usize + $crate::mem::size_of_val(&$root.$($begin)*))
-    };
-    (@helper $root:ident, $(# $begin:tt)+ [] $tt:tt $($rest:tt)*) => {
-        span_of!(@helper $root, $(#$begin)* #$tt [] $($rest)*)
-    };
-    (@helper $root:ident, [] $tt:tt $($rest:tt)*) => {
-        span_of!(@helper $root, #$tt [] $($rest)*)
-    };
+    }};
+    // Just one field.
+    (@helper $root:ident, $parent:tt, # $begin:tt []) => {{
+        _memoffset__field_check!($parent, $begin);
+        (&(*$root).$begin as *const _ as usize,
+         &(*$root).$begin as *const _ as usize + $crate::mem::size_of_val(&(*$root).$begin))
+    }};
+    // Parsing.
+    (@helper $root:ident, $parent:tt, $(# $begin:tt)+ [] $tt:tt $($rest:tt)*) => {{
+        span_of!(@helper $root, $parent, $(#$begin)* #$tt [] $($rest)*)
+    }};
+    (@helper $root:ident, $parent:tt, [] $tt:tt $($rest:tt)*) => {{
+        span_of!(@helper $root, $parent, #$tt [] $($rest)*)
+    }};
 
-    ($sty:ty, $($exp:tt)+) => ({
-        unsafe { 
-            let root: $sty = $crate::mem::uninitialized();
-            let base = &root as *const _ as usize;
-            let (begin, end) = span_of!(@helper root, [] $($exp)*);
+    // Entry point.
+    ($sty:tt, $($exp:tt)+) => ({
+        unsafe {
+            // Get a base pointer.
+            _memoffset__let_base_ptr!(root, $sty);
+            let base = root as usize;
+            let (begin, end) = span_of!(@helper root, $sty, [] $($exp)*);
             begin-base..end-base
         }
     });
@@ -132,51 +160,59 @@ macro_rules! span_of {
 
 #[cfg(test)]
 mod tests {
-    use ::core::mem;
-
-    #[repr(C, packed)]
-    struct Foo {
-        a: u32,
-        b: [u8; 4],
-        c: i64,
-    }
+    use core::mem;
 
     #[test]
     fn span_simple() {
+        #[repr(C)]
+        struct Foo {
+            a: u32,
+            b: [u8; 2],
+            c: i64,
+        }
+
         assert_eq!(span_of!(Foo, a), 0..4);
-        assert_eq!(span_of!(Foo, b), 4..8);
-        assert_eq!(span_of!(Foo, c), 8..16);
+        assert_eq!(span_of!(Foo, b), 4..6);
+        assert_eq!(span_of!(Foo, c), 8..8 + 8);
     }
 
     #[test]
-    fn span_index() {
-        assert_eq!(span_of!(Foo, b[1]), 5..6);
+    #[cfg(not(miri))] // this creates unaligned references
+    fn span_simple_packed() {
+        #[repr(C, packed)]
+        struct Foo {
+            a: u32,
+            b: [u8; 2],
+            c: i64,
+        }
+
+        assert_eq!(span_of!(Foo, a), 0..4);
+        assert_eq!(span_of!(Foo, b), 4..6);
+        assert_eq!(span_of!(Foo, c), 6..6 + 8);
     }
 
     #[test]
     fn span_forms() {
-        #[repr(C, packed)]
+        #[repr(C)]
         struct Florp {
             a: u32,
         }
 
-        #[repr(C, packed)]
+        #[repr(C)]
         struct Blarg {
             x: u64,
             y: [u8; 56],
             z: Florp,
-            egg: [[u8; 4]; 4],
+            egg: [[u8; 4]; 5],
         }
 
         // Love me some brute force
         assert_eq!(0..8, span_of!(Blarg, x));
-        assert_eq!(64..68, span_of!(Blarg, z.a));
-        assert_eq!(79..80, span_of!(Blarg, egg[2][3]));
+        assert_eq!(64..68, span_of!(Blarg, z));
+        assert_eq!(68..mem::size_of::<Blarg>(), span_of!(Blarg, egg));
 
-        assert_eq!(8..64, span_of!(Blarg, y[0]..z));
-        assert_eq!(0..42, span_of!(Blarg, x..y[34]));
-        assert_eq!(0..64, span_of!(Blarg, x     ..= y));
-        assert_eq!(58..68, span_of!(Blarg, y[50] ..= z));
+        assert_eq!(8..64, span_of!(Blarg, y..z));
+        assert_eq!(0..64, span_of!(Blarg, x..=y));
     }
 
     #[test]
@@ -198,18 +234,11 @@ mod tests {
         assert_eq!(span_of!(Test, ..=x), 0..8);
         assert_eq!(span_of!(Test, ..y), 0..8);
         assert_eq!(span_of!(Test, ..=y), 0..64);
-        assert_eq!(span_of!(Test, ..y[0]), 0..8);
-        assert_eq!(span_of!(Test, ..=y[0]), 0..9);
         assert_eq!(span_of!(Test, ..z), 0..64);
         assert_eq!(span_of!(Test, ..=z), 0..68);
-        assert_eq!(span_of!(Test, ..z.foo), 0..64);
-        assert_eq!(span_of!(Test, ..=z.foo), 0..68);
         assert_eq!(span_of!(Test, ..egg), 0..68);
         assert_eq!(span_of!(Test, ..=egg), 0..84);
-        assert_eq!(span_of!(Test, ..egg[0]), 0..68);
-        assert_eq!(span_of!(Test, ..=egg[0]), 0..72);
-        assert_eq!(span_of!(Test, ..egg[0][0]), 0..68);
-        assert_eq!(span_of!(Test, ..=egg[0][0]), 0..69);
+        assert_eq!(span_of!(Test, ..), 0..mem::size_of::<Test>());
         assert_eq!(
             span_of!(Test, x..),
             offset_of!(Test, x)..mem::size_of::<Test>()
@@ -218,30 +247,15 @@ mod tests {
             span_of!(Test, y..),
             offset_of!(Test, y)..mem::size_of::<Test>()
         );
-        assert_eq!(
-            span_of!(Test, y[0]..),
-            offset_of!(Test, y[0])..mem::size_of::<Test>()
-        );
+
         assert_eq!(
             span_of!(Test, z..),
             offset_of!(Test, z)..mem::size_of::<Test>()
         );
-        assert_eq!(
-            span_of!(Test, z.foo..),
-            offset_of!(Test, z.foo)..mem::size_of::<Test>()
-        );
         assert_eq!(
             span_of!(Test, egg..),
             offset_of!(Test, egg)..mem::size_of::<Test>()
         );
-        assert_eq!(
-            span_of!(Test, egg[0]..),
-            offset_of!(Test, egg[0])..mem::size_of::<Test>()
-        );
-        assert_eq!(
-            span_of!(Test, egg[0][0]..),
-            offset_of!(Test, egg[0][0])..mem::size_of::<Test>()
-        );
         assert_eq!(
             span_of!(Test, x..y),
             offset_of!(Test, x)..offset_of!(Test, y)
@@ -250,25 +264,5 @@ mod tests {
             span_of!(Test, x..=y),
             offset_of!(Test, x)..offset_of!(Test, y) + mem::size_of::<[u8; 56]>()
         );
-        assert_eq!(
-            span_of!(Test, x..y[4]),
-            offset_of!(Test, x)..offset_of!(Test, y[4])
-        );
-        assert_eq!(
-            span_of!(Test, x..=y[4]),
-            offset_of!(Test, x)..offset_of!(Test, y) + mem::size_of::<[u8; 5]>()
-        );
-        assert_eq!(
-            span_of!(Test, x..z.foo),
-            offset_of!(Test, x)..offset_of!(Test, z.foo)
-        );
-        assert_eq!(
-            span_of!(Test, x..=z.foo),
-            offset_of!(Test, x)..offset_of!(Test, z.foo) + mem::size_of::<u32>()
-        );
-        assert_eq!(
-            span_of!(Test, egg[0][0]..egg[1][0]),
-            offset_of!(Test, egg[0][0])..offset_of!(Test, egg[1][0])
-        );
     }
 }