munge-0.4.1/.cargo_vcs_info.json0000644000000001430000000000100121470ustar { "git": { "sha1": "aea7ab19a38fc2627f1bc6a2a071b0d40c70810e" }, "path_in_vcs": "munge" }munge-0.4.1/Cargo.toml0000644000000023550000000000100101540ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "munge" version = "0.4.1" authors = ["David Koloski "] build = false autobins = false autoexamples = false autotests = false autobenches = false description = "Macro for custom destructuring" documentation = "https://docs.rs/munge" readme = "README.md" keywords = [ "macro", "no_std", ] categories = [ "no-std", "no-std::no-alloc", "rust-patterns", ] license = "MIT" repository = "https://github.com/djkoloski/munge" [lib] name = "munge" path = "src/lib.rs" [[test]] name = "tests" path = "tests/tests.rs" [dependencies.munge_macro] version = "=0.4.1" default-features = false [dev-dependencies.rustversion] version = "1" default-features = false [dev-dependencies.trybuild] version = "1" default-features = false munge-0.4.1/Cargo.toml.orig000064400000000000000000000010300072674642500136520ustar 00000000000000[package] name = "munge" description = "Macro for custom destructuring" version.workspace = true authors.workspace = true edition.workspace = true license.workspace = true readme.workspace = true repository.workspace = true keywords.workspace = true categories.workspace = true documentation = "https://docs.rs/munge" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] munge_macro.workspace = true [dev-dependencies] rustversion.workspace = true trybuild.workspace = true munge-0.4.1/LICENSE000064400000000000000000000020440072674642500117760ustar 00000000000000Copyright 2024 David Koloski Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. munge-0.4.1/README.md000064400000000000000000000070010072674642500122460ustar 00000000000000# `munge` [![crates.io badge]][crates.io] [![docs badge]][docs] [![license badge]][license] [crates.io badge]: https://img.shields.io/crates/v/munge.svg [crates.io]: https://crates.io/crates/munge [docs badge]: https://img.shields.io/docsrs/munge [docs]: https://docs.rs/munge [license badge]: https://img.shields.io/badge/license-MIT-blue.svg [license]: https://github.com/rkyv/munge/blob/master/LICENSE Munge makes it easy and safe to destructure `MaybeUninit`s, `Cell`s, `UnsafeCell`s, `ManuallyDrop`s, and more. ## Documentation - [munge](https://docs.rs/munge), the core library - [munge_macro](https://docs.rs/munge_macro), the proc macro at the core of munge. ## Examples Initialize `MaybeUninit`s: ```rust use core::mem::MaybeUninit; use munge::munge; pub struct Example { a: u32, b: (char, f32), } let mut mu = MaybeUninit::::uninit(); munge!(let Example { a, b: (c, mut f) } = &mut mu); assert_eq!(a.write(10), &10); assert_eq!(c.write('x'), &'x'); assert_eq!(f.write(3.14), &3.14); // Note that `mut` bindings can be reassigned like you'd expect: f = &mut MaybeUninit::uninit(); // SAFETY: `mu` is completely initialized. let init = unsafe { mu.assume_init() }; assert_eq!(init.a, 10); assert_eq!(init.b.0, 'x'); assert_eq!(init.b.1, 3.14); ``` Destructure `Cell`s: ```rust use core::cell::Cell; use munge::munge; pub struct Example { a: u32, b: (char, f32), } let value = Example { a: 10, b: ('x', 3.14), }; let cell = Cell::::new(value); munge!(let Example { a, b: (c, f) } = &cell); assert_eq!(a.get(), 10); a.set(42); assert_eq!(c.get(), 'x'); c.set('!'); assert_eq!(f.get(), 3.14); f.set(1.41); let value = cell.into_inner(); assert_eq!(value.a, 42); assert_eq!(value.b.0, '!'); assert_eq!(value.b.1, 1.41); ``` You can even extend munge to work with your own types by implementing its `Destructure` and `Restructure` traits: ```rust use munge::{Destructure, Restructure, Move, munge}; pub struct Invariant(T); impl Invariant { /// # Safety /// /// `value` must uphold my custom invariant. pub unsafe fn new_unchecked(value: T) -> Self { Self(value) } pub fn unwrap(self) -> T { self.0 } } // SAFETY: // - `Invariant` is destructured by move, so its `Destructuring` type is // `Move`. // - `underlying` returns a pointer to its inner type, so it is guaranteed // to be non-null, properly aligned, and valid for reads. unsafe impl Destructure for Invariant { type Underlying = T; type Destructuring = Move; fn underlying(&mut self) -> *mut Self::Underlying { &mut self.0 as *mut Self::Underlying } } // SAFETY: `restructure` returns an `Invariant` that takes ownership of // the restructured field because `Invariant` is destructured by move. unsafe impl Restructure for Invariant { type Restructured = Invariant; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: The caller has guaranteed that `ptr` is a pointer to a // subfield of some `T`, so it must be properly aligned, valid for // reads, and initialized. We may move the fields because the // destructuring type for `Invariant` is `Move`. let value = unsafe { ptr.read() }; Invariant(value) } } // SAFETY: `(1, 2, 3)` upholds my custom invariant. let value = unsafe { Invariant::new_unchecked((1, 2, 3)) }; munge!(let (one, two, three) = value); assert_eq!(one.unwrap(), 1); assert_eq!(two.unwrap(), 2); assert_eq!(three.unwrap(), 3); ``` munge-0.4.1/example.md000064400000000000000000000057060072674642500127560ustar 00000000000000 Initialize `MaybeUninit`s: ```rust use core::mem::MaybeUninit; use munge::munge; pub struct Example { a: u32, b: (char, f32), } let mut mu = MaybeUninit::::uninit(); munge!(let Example { a, b: (c, mut f) } = &mut mu); assert_eq!(a.write(10), &10); assert_eq!(c.write('x'), &'x'); assert_eq!(f.write(3.14), &3.14); // Note that `mut` bindings can be reassigned like you'd expect: f = &mut MaybeUninit::uninit(); // SAFETY: `mu` is completely initialized. let init = unsafe { mu.assume_init() }; assert_eq!(init.a, 10); assert_eq!(init.b.0, 'x'); assert_eq!(init.b.1, 3.14); ``` Destructure `Cell`s: ```rust use core::cell::Cell; use munge::munge; pub struct Example { a: u32, b: (char, f32), } let value = Example { a: 10, b: ('x', 3.14), }; let cell = Cell::::new(value); munge!(let Example { a, b: (c, f) } = &cell); assert_eq!(a.get(), 10); a.set(42); assert_eq!(c.get(), 'x'); c.set('!'); assert_eq!(f.get(), 3.14); f.set(1.41); let value = cell.into_inner(); assert_eq!(value.a, 42); assert_eq!(value.b.0, '!'); assert_eq!(value.b.1, 1.41); ``` You can even extend munge to work with your own types by implementing its `Destructure` and `Restructure` traits: ```rust use munge::{Destructure, Restructure, Move, munge}; pub struct Invariant(T); impl Invariant { /// # Safety /// /// `value` must uphold my custom invariant. pub unsafe fn new_unchecked(value: T) -> Self { Self(value) } pub fn unwrap(self) -> T { self.0 } } // SAFETY: // - `Invariant` is destructured by move, so its `Destructuring` type is // `Move`. // - `underlying` returns a pointer to its inner type, so it is guaranteed // to be non-null, properly aligned, and valid for reads. unsafe impl Destructure for Invariant { type Underlying = T; type Destructuring = Move; fn underlying(&mut self) -> *mut Self::Underlying { &mut self.0 as *mut Self::Underlying } } // SAFETY: `restructure` returns an `Invariant` that takes ownership of // the restructured field because `Invariant` is destructured by move. unsafe impl Restructure for Invariant { type Restructured = Invariant; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: The caller has guaranteed that `ptr` is a pointer to a // subfield of some `T`, so it must be properly aligned, valid for // reads, and initialized. We may move the fields because the // destructuring type for `Invariant` is `Move`. let value = unsafe { ptr.read() }; Invariant(value) } } // SAFETY: `(1, 2, 3)` upholds my custom invariant. let value = unsafe { Invariant::new_unchecked((1, 2, 3)) }; munge!(let (one, two, three) = value); assert_eq!(one.unwrap(), 1); assert_eq!(two.unwrap(), 2); assert_eq!(three.unwrap(), 3); ``` munge-0.4.1/src/__macro.rs000064400000000000000000000032020072674642500135220ustar 00000000000000use core::{hint::unreachable_unchecked, marker::PhantomData}; use crate::{internal, Borrow, Destructure, Restructure}; pub fn make_destructurer( value: T, ) -> >::Destructurer where T::Destructuring: internal::DestructuringFor, { internal::Destructurer::new(value) } pub fn destructurer_ptr( destructurer: &mut T, ) -> *mut ::Underlying { Destructure::underlying(destructurer.inner_mut()) } /// # Safety /// /// `test_destructurer` may not be called. pub fn test_destructurer<'a, T: internal::Test<'a>>(_: &'a mut T) -> T::Test { // SAFETY: `test_destructurer` may not be called. unsafe { unreachable_unchecked() } } /// # Safety /// /// `ptr` must be a properly-aligned pointer to a subfield of the pointer /// underlying the inner value of `destructurer`. pub unsafe fn restructure_destructurer( destructurer: &T, ptr: *mut U, ) -> >::Restructured where T::Inner: Restructure, { // SAFETY: The caller has guaranteed that `ptr` is a properly-aligned // pointer to a subfield of the pointer underlying the inner value of // `destructurer`. unsafe { Restructure::restructure( internal::Destructurer::inner(destructurer), ptr, ) } } pub fn get_destructure(_: &T) -> PhantomData where T: internal::Destructurer, { PhantomData } pub fn only_borrow_destructuring_may_use_rest_patterns< T: Destructure, >( _: PhantomData, ) { } munge-0.4.1/src/impls.rs000064400000000000000000000372620072674642500132640ustar 00000000000000use core::{ cell::{Cell, UnsafeCell}, mem::{transmute, ManuallyDrop, MaybeUninit}, ptr::read, }; use crate::{Borrow, Destructure, Move, Restructure}; // MaybeUninit // SAFETY: // - `MaybeUninit` is destructured by move, so its `Destructuring` type is // `Move`. // - `underlying` returns a pointer to its inner type, so it is guaranteed to be // non-null, properly aligned, and valid for reads. unsafe impl Destructure for MaybeUninit { type Underlying = T; type Destructuring = Move; fn underlying(&mut self) -> *mut Self::Underlying { self.as_ptr() as *mut Self::Underlying } } // SAFETY: `restructure` returns a `MaybeUninit` that takes ownership of the // restructured field because `MaybeUninit` is destructured by mvoe. unsafe impl Restructure for MaybeUninit { type Restructured = MaybeUninit; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: The caller has guaranteed that `ptr` is a pointer to a // subfield of some `T`, so it must be properly aligned, valid for // reads, and initialized. We may move the fields because the // destructuring type for `MaybeUninit` is `Move`. unsafe { read(ptr.cast()) } } } // &MaybeUninit // SAFETY: // - `&MaybeUninit` is destructured by borrow, so its `Destructuring` type is // `Borrow`. // - `underlying` returns a pointer to its inner type, so it is guaranteed to be // non-null, properly aligned, and valid for reads. unsafe impl<'a, T> Destructure for &'a MaybeUninit { type Underlying = T; type Destructuring = Borrow; fn underlying(&mut self) -> *mut Self::Underlying { self.as_ptr() as *mut Self::Underlying } } // SAFETY: `restructure` returns a `&MaybeUninit` that borrows the // restructured field because `&MaybeUninit` is destructured by borrow. unsafe impl<'a, T, U: 'a> Restructure for &'a MaybeUninit { type Restructured = &'a MaybeUninit; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: The caller has guaranteed that `ptr` points to a subfield of // some `MaybeUninit`, so it's safe to dereference. Because the // destructuring type for `&MaybeUninit` is `Borrow`, we may create a // disjoint borrow of it for `'a`. unsafe { &*ptr.cast() } } } // &mut MaybeUninit // SAFETY: // - `&mut MaybeUninit` is destructured by borrow, so its `Destructuring` // type is `Borrow`. // - `underlying` returns a pointer to its inner type, so it is guaranteed to be // non-null, properly aligned, and valid for reads. unsafe impl<'a, T> Destructure for &'a mut MaybeUninit { type Underlying = T; type Destructuring = Borrow; fn underlying(&mut self) -> *mut Self::Underlying { MaybeUninit::as_mut_ptr(self) } } // SAFETY: `restructure` returns a `&mut MaybeUninit` that borrows the // restructured field because `&mut MaybeUninit` is destructured by borrow. unsafe impl<'a, T, U: 'a> Restructure for &'a mut MaybeUninit { type Restructured = &'a mut MaybeUninit; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: The caller has guaranteed that `ptr` points to a subfield of // some `MaybeUninit`, so it's safe to dereference. Because the // destructuring type for `&mut MaybeUninit` is `Borrow`, we may // create a disjoint borrow of it for `'a`. unsafe { &mut *ptr.cast() } } } // Cell // SAFETY: // - `Cell` is destructured by move, so its `Destructuring` type is `Move`. // - `underlying` returns a pointer to its inner type, so it is guaranteed to be // non-null, properly aligned, and valid for reads. unsafe impl Destructure for Cell { type Underlying = T; type Destructuring = Move; fn underlying(&mut self) -> *mut Self::Underlying { self.as_ptr() } } // SAFETY: `restructure` returns a `Cell` that takes ownership of the // restructured field because `Cell` is destructured by move. unsafe impl Restructure for Cell { type Restructured = Cell; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: The caller has guaranteed that `ptr` is a pointer to a // subfield of some `T`, so it must be properly aligned, valid for // reads, and initialized. We may move the fields because the // destructuring type for `Cell` is `Move`. unsafe { read(ptr.cast_const().cast()) } } } // &Cell // SAFETY: // - `&Cell` is destructured by borrow, so its `Destructuring` type is // `Borrow`. // - `underlying` returns a pointer to its inner type, so it is guaranteed to be // non-null, properly aligned, and valid for reads. unsafe impl<'a, T: ?Sized> Destructure for &'a Cell { type Underlying = T; type Destructuring = Borrow; fn underlying(&mut self) -> *mut Self::Underlying { self.as_ptr() } } // SAFETY: `restructure` returns a `&Cell` that borrows the restructured // field because `&Cell` is destructured by borrow. unsafe impl<'a, T: ?Sized, U: 'a + ?Sized> Restructure for &'a Cell { type Restructured = &'a Cell; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: `Cell` is `repr(transparent)` and so guaranteed to have // the same representation as the `U` it contains. Therefore, the // pointer metadata for `*const Cell` is the same as the metadata for // `*mut U`, and transmuting between the two types is sound. let ptr = unsafe { transmute::<*mut U, *const Cell>(ptr) }; // SAFETY: The caller has guaranteed that `ptr` points to a subfield of // some `Cell`, so it's safe to dereference. Because the // destructuring type for `&Cell` is `Borrow`, we may create a // disjoint borrow of it for `'a`. unsafe { &*ptr } } } // &mut Cell // SAFETY: // - `&mut Cell` is destructured by borrow, so its `Destructuring` type is // `Borrow`. // - `underlying` returns a pointer to its inner type, so it is guaranteed to be // non-null, properly aligned, and valid for reads. unsafe impl<'a, T: ?Sized> Destructure for &'a mut Cell { type Underlying = T; type Destructuring = Borrow; fn underlying(&mut self) -> *mut Self::Underlying { self.as_ptr() } } // SAFETY: `restructure` returns a `&mut Cell` that borrows the restructured // field because `&mut Cell` is destructured by borrow. unsafe impl<'a, T: ?Sized, U: 'a + ?Sized> Restructure for &'a mut Cell { type Restructured = &'a mut Cell; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: `Cell` is `repr(transparent)` and so guaranteed to have // the same representation as the `U` it contains. Therefore, the // pointer metadata for `*mut Cell` is the same as the metadata for // `*mut U`, and transmuting between the two types is sound. let ptr = unsafe { transmute::<*mut U, *mut Cell>(ptr) }; // SAFETY: The caller has guaranteed that `ptr` points to a subfield of // some `Cell`, so it's safe to dereference. Because the // destructuring type for `&mut Cell` is `Borrow`, we may create a // disjoint borrow of it for `'a`. unsafe { &mut *ptr } } } // UnsafeCell // SAFETY: // - `UnsafeCell` is destructured by move, so its `Destructuring` type is // `Move`. // - `underlying` returns a pointer to its inner type, so it is guaranteed to be // non-null, properly aligned, and valid for reads. unsafe impl Destructure for UnsafeCell { type Underlying = T; type Destructuring = Move; fn underlying(&mut self) -> *mut Self::Underlying { self.get() } } // SAFETY: `restructure` returns a `UnsafeCell` that takes ownership of the // restructured field because `UnsafeCell` is destructured by move. unsafe impl Restructure for UnsafeCell { type Restructured = UnsafeCell; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: The caller has guaranteed that `ptr` is a pointer to a // subfield of some `T`, so it must be properly aligned, valid for // reads, and initialized. We may move the fields because the // destructuring type for `UnsafeCell` is `Move`. unsafe { read(ptr.cast()) } } } // &UnsafeCell // SAFETY: // - `&UnsafeCell` is destructured by borrow, so its `Destructuring` type is // `Borrow`. // - `underlying` returns a pointer to its inner type, so it is guaranteed to be // non-null, properly aligned, and valid for reads. unsafe impl<'a, T: ?Sized> Destructure for &'a UnsafeCell { type Underlying = T; type Destructuring = Borrow; fn underlying(&mut self) -> *mut Self::Underlying { self.get() } } // SAFETY: `restructure` returns a `&UnsafeCell` that borrows the // restructured field because `&UnsafeCell` is destructured by borrow. unsafe impl<'a, T, U> Restructure for &'a UnsafeCell where T: ?Sized, U: 'a + ?Sized, { type Restructured = &'a UnsafeCell; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: `UnsafeCell` is `repr(transparent)` and so guaranteed to // have the same representation as the `U` it contains. Therefore, the // pointer metadata for `*const UnsafeCell` is the same as the // metadata for `*mut U`, and transmuting between the two types is // sound. let ptr = unsafe { transmute::<*mut U, *const UnsafeCell>(ptr) }; // SAFETY: The caller has guaranteed that `ptr` points to a subfield of // some `UnsafeCell`, so it's safe to dereference. Because the // destructuring type for `&UnsafeCell` is `Borrow`, we may create a // disjoint borrow of it for `'a`. unsafe { &*ptr } } } // &mut UnsafeCell // SAFETY: // - `&mut UnsafeCell` is destructured by borrow, so its `Destructuring` type // is `Borrow`. // - `underlying` returns a pointer to its inner type, so it is guaranteed to be // non-null, properly aligned, and valid for reads. unsafe impl<'a, T: ?Sized> Destructure for &'a mut UnsafeCell { type Underlying = T; type Destructuring = Borrow; fn underlying(&mut self) -> *mut Self::Underlying { self.get() } } // SAFETY: `restructure` returns a `&mut UnsafeCell` that borrows the // restructured field because `&mut UnsafeCell` is destructured by borrow. unsafe impl<'a, T, U> Restructure for &'a mut UnsafeCell where T: ?Sized, U: 'a + ?Sized, { type Restructured = &'a mut UnsafeCell; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: `UnsafeCell` is `repr(transparent)` and so guaranteed to // have the same representation as the `U` it contains. Therefore, the // pointer metadata for `*mut UnsafeCell` is the same as the metadata // for `*mut U`, and transmuting between the two types is sound. let ptr = unsafe { transmute::<*mut U, *mut UnsafeCell>(ptr) }; // SAFETY: The caller has guaranteed that `ptr` points to a subfield of // some `UnsafeCell`, so it's safe to dereference. Because the // destructuring type for `&mut UnsafeCell` is `Borrow`, we may // create a disjoint borrow of it for `'a`. unsafe { &mut *ptr } } } // ManuallyDrop // SAFETY: // - `ManuallyDrop` is destructured by move, so its `Destructuring` type is // `Move`. // - `underlying` returns a pointer to its inner type, so it is guaranteed to be // non-null, properly aligned, and valid for reads. unsafe impl Destructure for ManuallyDrop { type Underlying = T; type Destructuring = Move; fn underlying(&mut self) -> *mut Self::Underlying { &mut **self as *mut Self::Underlying } } // SAFETY: `restructure` returns a `ManuallyDrop` that takes ownership of the // restructured field because `ManuallyDrop` is destructured by move. unsafe impl Restructure for ManuallyDrop { type Restructured = ManuallyDrop; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: The caller has guaranteed that `ptr` is a pointer to a // subfield of some `T`, so it must be properly aligned, valid for // reads, and initialized. We may move the fields because the // destructuring type for `ManuallyDrop` is `Move`. unsafe { read(ptr.cast()) } } } // &ManuallyDrop // SAFETY: // - `&ManuallyDrop` is destructured by borrow, so its `Destructuring` type // is `Borrow`. // - `underlying` returns a pointer to its inner type, so it is guaranteed to be // non-null, properly aligned, and valid for reads. unsafe impl<'a, T: ?Sized> Destructure for &'a ManuallyDrop { type Underlying = T; type Destructuring = Borrow; fn underlying(&mut self) -> *mut Self::Underlying { (&***self as *const Self::Underlying).cast_mut() } } // SAFETY: `restructure` returns a `&ManuallyDrop` that borrows the // restructured field because `&ManuallyDrop` is destructured by borrow. unsafe impl<'a, T, U> Restructure for &'a ManuallyDrop where T: ?Sized, U: 'a + ?Sized, { type Restructured = &'a ManuallyDrop; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: `ManuallyDrop` is `repr(transparent)` and so guaranteed to // have the same representation as the `U` it contains. Therefore, the // pointer metadata for `*const ManuallyDrop` is the same as the // metadata for `*mut U`, and transmuting between the two types is // sound. let ptr = unsafe { transmute::<*mut U, *const ManuallyDrop>(ptr) }; // SAFETY: The caller has guaranteed that `ptr` points to a subfield of // some `ManuallyDrop`, so it's safe to dereference. Because the // destructuring type for `&ManuallyDrop` is `Borrow`, we may create // a disjoint borrow of it for `'a`. unsafe { &*ptr } } } // &mut ManuallyDrop // SAFETY: // - `&mut ManuallyDrop` is destructured by borrow, so its `Destructuring` // type is `Borrow`. // - `underlying` returns a pointer to its inner type, so it is guaranteed to be // non-null, properly aligned, and valid for reads. unsafe impl<'a, T: ?Sized> Destructure for &'a mut ManuallyDrop { type Underlying = T; type Destructuring = Borrow; fn underlying(&mut self) -> *mut Self::Underlying { &mut ***self as *mut Self::Underlying } } // SAFETY: `restructure` returns a `&mut ManuallyDrop` that borrows the // restructured field because `&mut ManuallyDrop` is destructured by // borrow. unsafe impl<'a, T, U> Restructure for &'a mut ManuallyDrop where T: ?Sized, U: 'a + ?Sized, { type Restructured = &'a mut ManuallyDrop; unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured { // SAFETY: `ManuallyDrop` is `repr(transparent)` and so guaranteed to // have the same representation as the `U` it contains. Therefore, the // pointer metadata for `*mut ManuallyDrop` is the same as the // metadata for `*mut U`, and transmuting between the two types is // sound. let ptr = unsafe { transmute::<*mut U, *mut ManuallyDrop>(ptr) }; // SAFETY: The caller has guaranteed that `ptr` points to a subfield of // some `ManuallyDrop`, so it's safe to dereference. Because the // destructuring type for `&mut ManuallyDrop` is `Borrow`, we may // create a disjoint borrow of it for `'a`. unsafe { &mut *ptr } } } munge-0.4.1/src/internal.rs000064400000000000000000000023240072674642500137430ustar 00000000000000use core::mem::ManuallyDrop; use crate::Destructure; pub trait Destructuring {} pub trait DestructuringFor: Destructuring { type Destructurer: Destructurer; } pub trait Destructurer { type Inner: Destructure; fn new(inner: Self::Inner) -> Self; fn inner(&self) -> &Self::Inner; fn inner_mut(&mut self) -> &mut Self::Inner; } pub trait Test<'a> { type Test; } pub struct Borrow(T); impl Destructurer for Borrow { type Inner = T; fn new(inner: T) -> Self { Self(inner) } fn inner(&self) -> &Self::Inner { &self.0 } fn inner_mut(&mut self) -> &mut Self::Inner { &mut self.0 } } impl<'a, T: 'a + Destructure> Test<'a> for Borrow { type Test = &'a T::Underlying; } pub struct Move(ManuallyDrop); impl Destructurer for Move { type Inner = T; fn new(inner: T) -> Self { Self(ManuallyDrop::new(inner)) } fn inner(&self) -> &Self::Inner { &self.0 } fn inner_mut(&mut self) -> &mut Self::Inner { &mut self.0 } } impl<'a, T: 'a + Destructure> Test<'a> for Move where T::Underlying: Sized, { type Test = T::Underlying; } munge-0.4.1/src/lib.rs000064400000000000000000000411620072674642500127000ustar 00000000000000//! Munge makes it easy and safe to destructure `MaybeUninit`s, `Cell`s, //! `UnsafeCell`s, `ManuallyDrop`s and more. //! //! Just use the `munge!` macro to destructure opaque types the same way you'd //! destructure a value. The `munge!` macro may be used to perform either borrow //! destructuring (e.g. `let (a, b) = c` where `c` is a reference) or move //! destructuring (e.g. `let (a, b) = c` where `c` is a value) depending on the //! type. //! //! Munge has no features and is always `#![no_std]`. //! //! ## Examples #![doc = include_str!("../example.md")] #![no_std] #![deny( future_incompatible, missing_docs, nonstandard_style, unsafe_op_in_unsafe_fn, unused, warnings, clippy::all, clippy::missing_safety_doc, clippy::undocumented_unsafe_blocks, rustdoc::broken_intra_doc_links, rustdoc::missing_crate_level_docs )] #![cfg_attr(all(docsrs, not(doctest)), feature(doc_cfg, doc_auto_cfg))] #[doc(hidden)] pub mod __macro; mod impls; mod internal; #[doc(hidden)] pub use munge_macro::munge_with_path; /// Destructures a type into /// /// # Example /// /// ``` /// # use core::mem::MaybeUninit; /// # use munge::munge; /// pub struct Example { /// a: u32, /// b: (char, f32), /// } /// /// let mut mu = MaybeUninit::::uninit(); /// /// munge!(let Example { a, b: (c, mut f) } = &mut mu); /// assert_eq!(a.write(10), &10); /// assert_eq!(c.write('x'), &'x'); /// assert_eq!(f.write(3.14), &3.14); /// // Note that `mut` bindings can be reassigned like you'd expect: /// let mut new_f = MaybeUninit::uninit(); /// f = &mut new_f; /// /// // SAFETY: `mu` is completely initialized. /// let init = unsafe { mu.assume_init() }; /// assert_eq!(init.a, 10); /// assert_eq!(init.b.0, 'x'); /// assert_eq!(init.b.1, 3.14); /// ``` #[macro_export] macro_rules! munge { ($($t:tt)*) => { $crate::munge_with_path!($crate => $($t)*) } } /// A type that can be destructured into its constituent parts. /// /// See the [crate docs](index.html#examples) for an example of implementing /// `Destructure` and `Restructure`. /// /// # Safety /// /// - [`Destructuring`](Destructure::Destructuring) must reflect the type of /// destructuring allowed for the type: /// - [`Borrow`] if the type is restructured by creating disjoint borrows of /// the fields of `Underlying`. /// - [`Move`] if the type may be restructured by moving the fields out of the /// destructured `Underlying`. /// - [`underlying`](Destructure::underlying) must return a pointer that is /// non-null, properly aligned, and valid for reads. pub unsafe trait Destructure: Sized { /// The underlying type that is destructured. type Underlying: ?Sized; /// The type of destructuring to perform. type Destructuring: internal::Destructuring; /// Returns a mutable pointer to the underlying type. fn underlying(&mut self) -> *mut Self::Underlying; } /// A type that can be "restructured" as a field of some containing type. /// /// See the [crate docs](index.html#examples) for an example of implementing /// `Destructure` and `Restructure`. /// /// # Safety /// /// [`restructure`](Restructure::restructure) must return a valid /// [`Restructured`](Restructure::Restructured) that upholds the invariants for /// its [`Destructuring`](Destructure::Destructuring): /// - If the type is destructured [by borrow](Borrow), then the `Restructured` /// value must behave as a disjoint borrow of a field of the underlying type. /// - If the type is destructured [by move](Move), then the `Restructured` value /// must move the fields out of the underlying type. pub unsafe trait Restructure: Destructure { /// The restructured version of this type. type Restructured; /// Restructures a pointer to this type into the target type. /// /// # Safety /// /// `ptr` must be a properly aligned pointer to a subfield of the pointer /// [`underlying`](Destructure::underlying) `self`. unsafe fn restructure(&self, ptr: *mut T) -> Self::Restructured; } /// Destructuring by borrow, e.g. `let (a, b) = c` where `c` is a reference. /// /// Borrow destructuring leaves the original value intact, only borrowing from /// the destructured value. Borrow destructuring may use rest patterns (`..`) /// because the original value is not moved and so it is safe to restructure /// only some of the fields of the destructured value. pub struct Borrow; impl internal::Destructuring for Borrow {} impl internal::DestructuringFor for Borrow { type Destructurer = internal::Borrow; } /// Destructuring by move, e.g. `let (a, b) = c` where `c` is a value. /// /// Move destructuring forgets the original value and moves each destructured /// field during restructuring. Move destructuring may not use rest patterns /// (`..`) because every field of the original value must be restructured, else /// they will be forgotten. pub struct Move; impl internal::Destructuring for Move {} impl internal::DestructuringFor for Move { type Destructurer = internal::Move; } #[cfg(test)] mod tests { use core::mem::MaybeUninit; #[test] fn project_tuple() { let mut mu = MaybeUninit::<(u32, char)>::uninit(); munge!(let (a, b) = &mut mu); assert_eq!(a.write(1), &1); assert_eq!(b.write('a'), &'a'); munge!(let (a, b,) = &mut mu); assert_eq!(a.write(2), &2); assert_eq!(b.write('b'), &'b'); munge!(let (a, _) = &mut mu); assert_eq!(a.write(3), &3); munge!(let (_, b) = &mut mu); assert_eq!(b.write('c'), &'c'); munge!(let (a, _,) = &mut mu); assert_eq!(a.write(3), &3); munge!(let (_, b,) = &mut mu); assert_eq!(b.write('c'), &'c'); munge!(let (mut a, mut b) = &mut mu); assert_eq!(a.write(4), &4); assert_eq!(b.write('d'), &'d'); let mut new_a = MaybeUninit::uninit(); a = &mut new_a; let mut new_b = MaybeUninit::uninit(); b = &mut new_b; let _ = a; let _ = b; munge!(let (a, ..) = &mut mu); assert_eq!(a.write(5), &5); // SAFETY: `mu` is completely initialized. let init = unsafe { mu.assume_init() }; assert_eq!(init.0, 5); assert_eq!(init.1, 'd'); } #[test] fn project_array() { let mut mu = MaybeUninit::<[u32; 2]>::uninit(); munge!(let [a, b] = &mut mu); assert_eq!(a.write(1), &1); assert_eq!(b.write(1), &1); munge!(let [a, b,] = &mut mu); assert_eq!(a.write(2), &2); assert_eq!(b.write(2), &2); munge!(let [a, _] = &mut mu); assert_eq!(a.write(3), &3); munge!(let [_, b] = &mut mu); assert_eq!(b.write(3), &3); munge!(let [a, _,] = &mut mu); assert_eq!(a.write(4), &4); munge!(let [_, b,] = &mut mu); assert_eq!(b.write(4), &4); munge!(let [mut a, mut b] = &mut mu); assert_eq!(a.write(5), &5); assert_eq!(b.write(5), &5); let mut new_a = MaybeUninit::uninit(); a = &mut new_a; let mut new_b = MaybeUninit::uninit(); b = &mut new_b; let _ = a; let _ = b; munge!(let [a, ..] = &mut mu); assert_eq!(a.write(6), &6); // SAFETY: `mu` is completely initialized. let init = unsafe { mu.assume_init() }; assert_eq!(init[0], 6); assert_eq!(init[1], 5); } #[test] fn project_struct() { pub struct Example { pub a: u32, pub b: char, } let mut mu = MaybeUninit::::uninit(); munge!(let Example { a, b } = &mut mu); assert_eq!(a.write(1), &1); assert_eq!(b.write('a'), &'a'); munge!(let Example { a, b, } = &mut mu); assert_eq!(a.write(2), &2); assert_eq!(b.write('b'), &'b'); munge!(let Example { a, b: x } = &mut mu); assert_eq!(a.write(3), &3); assert_eq!(x.write('c'), &'c'); munge!(let Example { a, b: x, } = &mut mu); assert_eq!(a.write(4), &4); assert_eq!(x.write('d'), &'d'); munge!(let Example { a: x, b } = &mut mu); assert_eq!(x.write(3), &3); assert_eq!(b.write('c'), &'c'); munge!(let Example { a: x, b, } = &mut mu); assert_eq!(x.write(4), &4); assert_eq!(b.write('d'), &'d'); munge!(let Example { a, b: _ } = &mut mu); assert_eq!(a.write(5), &5); munge!(let Example { a, b: _, } = &mut mu); assert_eq!(a.write(6), &6); munge!(let Example { mut a, mut b } = &mut mu); assert_eq!(a.write(7), &7); assert_eq!(b.write('e'), &'e'); let mut new_a = MaybeUninit::uninit(); a = &mut new_a; let mut new_b = MaybeUninit::uninit(); b = &mut new_b; let _ = a; let _ = b; munge!(let Example { a: mut x, b: mut y } = &mut mu); assert_eq!(x.write(8), &8); assert_eq!(y.write('f'), &'f'); let mut new_x = MaybeUninit::uninit(); x = &mut new_x; let mut new_y = MaybeUninit::uninit(); y = &mut new_y; let _ = x; let _ = y; munge!(let Example { b, .. } = &mut mu); assert_eq!(b.write('g'), &'g'); // SAFETY: `mu` is completely initialized. let init = unsafe { mu.assume_init() }; assert_eq!(init.a, 8); assert_eq!(init.b, 'g'); } #[test] fn project_tuple_struct() { struct Example(u32, char); let mut mu = MaybeUninit::::uninit(); munge!(let Example(a, b) = &mut mu); assert_eq!(a.write(1), &1); assert_eq!(b.write('a'), &'a'); munge!(let Example(a, b,) = &mut mu); assert_eq!(a.write(2), &2); assert_eq!(b.write('b'), &'b'); munge!(let Example(a, _) = &mut mu); assert_eq!(a.write(3), &3); munge!(let Example(_, b) = &mut mu); assert_eq!(b.write('c'), &'c'); munge!(let Example(a, _,) = &mut mu); assert_eq!(a.write(3), &3); munge!(let Example(_, b,) = &mut mu); assert_eq!(b.write('d'), &'d'); munge!(let Example(mut a, mut b) = &mut mu); assert_eq!(a.write(4), &4); assert_eq!(b.write('e'), &'e'); let mut new_a = MaybeUninit::uninit(); a = &mut new_a; let mut new_b = MaybeUninit::uninit(); b = &mut new_b; let _ = a; let _ = b; munge!(let Example(a, ..) = &mut mu); assert_eq!(a.write(5), &5); // SAFETY: `mu` is completely initialized. let init = unsafe { mu.assume_init() }; assert_eq!(init.0, 5); assert_eq!(init.1, 'e'); } #[test] fn project_generic() { struct Example(u32, T); let mut mu = MaybeUninit::>::uninit(); munge!(let Example(a, b) = &mut mu); assert_eq!(a.write(1), &1); assert_eq!(b.write('a'), &'a'); munge!(let Example(a, b,) = &mut mu); assert_eq!(a.write(2), &2); assert_eq!(b.write('b'), &'b'); munge!(let Example(a, _) = &mut mu); assert_eq!(a.write(3), &3); munge!(let Example(_, b) = &mut mu); assert_eq!(b.write('c'), &'c'); munge!(let Example(a, _,) = &mut mu); assert_eq!(a.write(3), &3); munge!(let Example(_, b,) = &mut mu); assert_eq!(b.write('c'), &'c'); munge!(let Example(a, ..) = &mut mu); assert_eq!(a.write(4), &4); // SAFETY: `mu` is completely initialized. let init = unsafe { mu.assume_init() }; assert_eq!(init.0, 4); assert_eq!(init.1, 'c'); let mut mu = MaybeUninit::>>::uninit(); munge!( let Example::>(a, Example::(b, c)) = &mut mu; ); assert_eq!(a.write(1), &1); assert_eq!(b.write(2), &2); assert_eq!(c.write('a'), &'a'); // SAFETY: `mu` is completely initialized. let init = unsafe { mu.assume_init() }; assert_eq!(init.0, 1); assert_eq!(init.1 .0, 2); assert_eq!(init.1 .1, 'a'); } #[test] fn project_nested_struct() { struct Inner { a: u32, b: char, } struct Outer { inner: Inner, c: i32, } let mut mu = MaybeUninit::::uninit(); munge!(let Outer { inner: Inner { a, b }, c } = &mut mu); assert_eq!(a.write(1), &1); assert_eq!(b.write('a'), &'a'); assert_eq!(c.write(2), &2); // SAFETY: `mu` is completely initialized. let init = unsafe { mu.assume_init() }; assert_eq!(init.inner.a, 1); assert_eq!(init.inner.b, 'a'); assert_eq!(init.c, 2); } #[test] fn project_nested_tuple() { let mut mu = MaybeUninit::<(u32, (char, u32))>::uninit(); munge!(let (a, (b, c)) = &mut mu); assert_eq!(a.write(1), &1); assert_eq!(b.write('a'), &'a'); assert_eq!(c.write(2), &2); // SAFETY: `mu` is completely initialized. let init = unsafe { mu.assume_init() }; assert_eq!(init, (1, ('a', 2))); } #[test] fn project_nested_array() { let mut mu = MaybeUninit::<[[u32; 2]; 2]>::uninit(); munge!(let [a, [b, c]] = &mut mu); assert_eq!(a.write([1, 2]), &[1, 2]); assert_eq!(b.write(3), &3); assert_eq!(c.write(4), &4); // SAFETY: `mu` is completely initialized. let init = unsafe { mu.assume_init() }; assert_eq!(init, [[1, 2], [3, 4]]); } #[test] fn generics() { struct Inner { a: u32, b: T, } struct Outer { inner: Inner, c: i32, } let mut mu = MaybeUninit::>::uninit(); munge!(let Outer { inner: Inner { a, b }, c } = &mut mu); assert_eq!(a.write(1), &1); assert_eq!(b.write('a'), &'a'); assert_eq!(c.write(2), &2); // SAFETY: `mu` is completely initialized. let init = unsafe { mu.assume_init() }; assert_eq!(init.inner.a, 1); assert_eq!(init.inner.b, 'a'); assert_eq!(init.c, 2); } #[test] fn cell() { use core::cell::Cell; pub struct Example { a: u32, b: (char, f32), } let value = Example { a: 10, b: ('x', core::f32::consts::PI), }; let cell = Cell::::new(value); munge!(let Example { a, b: (c, f) } = &cell); assert_eq!(a.get(), 10); a.set(42); assert_eq!(c.get(), 'x'); c.set('!'); assert_eq!(f.get(), core::f32::consts::PI); f.set(1.41); let value = cell.into_inner(); assert_eq!(value.a, 42); assert_eq!(value.b.0, '!'); assert_eq!(value.b.1, 1.41); } #[test] fn maybe_uninit_value() { let mu = MaybeUninit::<(u32, char)>::new((10_000, 'x')); munge!(let (a, b) = mu); assert_eq!(unsafe { a.assume_init() }, 10_000); assert_eq!(unsafe { b.assume_init() }, 'x'); } #[test] fn cell_value() { use core::cell::Cell; let cell = Cell::<(u32, char)>::new((10_000, 'x')); munge!(let (a, b) = cell); assert_eq!(a.get(), 10_000); assert_eq!(b.get(), 'x'); } #[test] fn unsafe_cell_value() { use core::cell::UnsafeCell; let uc = UnsafeCell::<(u32, char)>::new((10_000, 'x')); munge!(let (mut a, mut b) = uc); assert_eq!(*a.get_mut(), 10_000); assert_eq!(*b.get_mut(), 'x'); } #[test] fn manually_drop_value() { use core::mem::ManuallyDrop; let md = ManuallyDrop::new((10_000, 'x')); munge!(let (a, b) = md); assert_eq!(*a, 10_000); assert_eq!(*b, 'x'); } #[test] fn struct_borrow_partial_destructuring() { use core::cell::Cell; struct Example { a: u32, b: u32, } let mut value = Cell::new(Example { a: 0, b: 1 }); munge!(let Example { a, .. } = &mut value); assert_eq!(a.get(), 0); a.set(2); assert_eq!(a.get(), 2); munge!(let Example { a: c, b: _ } = &value); assert_eq!(c.get(), 2); c.set(3); assert_eq!(c.get(), 3); } #[test] fn tuple_borrow_partial_destructuring() { use core::cell::Cell; struct Example(u32, u32); let mut value = Cell::new(Example(0, 1)); munge!(let Example(a, ..) = &mut value); assert_eq!(a.get(), 0); a.set(2); assert_eq!(a.get(), 2); munge!(let Example(c, _) = &value); assert_eq!(c.get(), 2); c.set(3); assert_eq!(c.get(), 3); } } munge-0.4.1/tests/tests.rs000064400000000000000000000002460072674642500136450ustar 00000000000000#[rustversion::attr(not(nightly), ignore)] #[cfg_attr(miri, ignore)] #[test] fn ui() { let t = trybuild::TestCases::new(); t.compile_fail("tests/ui/*.rs"); } munge-0.4.1/tests/ui/double_borrow.rs000064400000000000000000000006750072674642500157720ustar 00000000000000use core::mem::MaybeUninit; use munge::munge; fn main() { struct Example { a: u32, b: u32, } let mut mu = MaybeUninit::::uninit(); munge!(let Example { a: a1, b: b1 } = &mut mu); assert_eq!(a1.write(1), &1); assert_eq!(b1.write(2), &2); munge!(let Example { a: a2, b: b2 } = &mut mu); assert_eq!(a1.write(3), &3); assert_eq!(b1.write(4), &4); a2.write(5); b2.write(6); } munge-0.4.1/tests/ui/double_borrow.stderr000064400000000000000000000007610072674642500166450ustar 00000000000000error[E0499]: cannot borrow `mu` as mutable more than once at a time --> tests/ui/double_borrow.rs:16:43 | 12 | munge!(let Example { a: a1, b: b1 } = &mut mu); | ------- first mutable borrow occurs here ... 16 | munge!(let Example { a: a2, b: b2 } = &mut mu); | ^^^^^^^ second mutable borrow occurs here 17 | assert_eq!(a1.write(3), &3); | -- first borrow later used here munge-0.4.1/tests/ui/move_while_borrowed.rs000064400000000000000000000006770072674642500171710ustar 00000000000000use core::mem::MaybeUninit; use munge::munge; fn main() { struct Example { a: u32, b: u32, } let mut mu = MaybeUninit::::uninit(); munge!(let Example { a, b } = &mut mu); assert_eq!(a.write(1), &1); assert_eq!(b.write(2), &2); // SAFETY: `mu` is completely initialized. let value = unsafe { mu.assume_init() }; assert_eq!(value.a, 1); assert_eq!(value.b, 2); a.write(3); } munge-0.4.1/tests/ui/move_while_borrowed.stderr000064400000000000000000000010040072674642500200310ustar 00000000000000error[E0505]: cannot move out of `mu` because it is borrowed --> tests/ui/move_while_borrowed.rs:17:26 | 10 | let mut mu = MaybeUninit::::uninit(); | ------ binding `mu` declared here 11 | 12 | munge!(let Example { a, b } = &mut mu); | ------- borrow of `mu` occurs here ... 17 | let value = unsafe { mu.assume_init() }; | ^^ move out of `mu` occurs here ... 21 | a.write(3); | - borrow later used here munge-0.4.1/tests/ui/packed.rs000064400000000000000000000011430072674642500143440ustar 00000000000000use core::mem::MaybeUninit; use munge::munge; fn main() { #[repr(packed)] struct Misalign { byte: u8, inner: T, } let mut mu = MaybeUninit::>>::uninit(); munge!( let Misalign { byte: a, inner: Misalign { byte: b, inner } } = &mut mu; ); assert_eq!(a.write(1), &1); assert_eq!(b.write(2), &2); assert_eq!(inner.write(3), &3); // SAFETY: `mu` is completely initialized. let init = unsafe { mu.assume_init() }; assert_eq!(init.byte, 1); assert_eq!(init.inner.byte, 2); assert_eq!(init.inner.inner, 3); } munge-0.4.1/tests/ui/packed.stderr000064400000000000000000000026650072674642500152350ustar 00000000000000error[E0793]: reference to packed field is unaligned --> tests/ui/packed.rs:14:60 | 14 | let Misalign { byte: a, inner: Misalign { byte: b, inner } } = &mut mu; | ^^^^^ | = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned --> tests/ui/packed.rs:24:5 | 24 | assert_eq!(init.inner.inner, 3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) munge-0.4.1/tests/ui/rest_patterns_ref_only.rs000064400000000000000000000005300072674642500177060ustar 00000000000000use core::mem::MaybeUninit; use munge::munge; fn main() { struct Struct { a: u32, b: u32, } let mut mu = MaybeUninit::::uninit(); munge!(let Struct { a, .. } = mu); struct Tuple(u32, u32); let mut mu = MaybeUninit::::uninit(); munge!(let Tuple(a, ..) = mu); } munge-0.4.1/tests/ui/rest_patterns_ref_only.stderr000064400000000000000000000031620072674642500205710ustar 00000000000000error[E0271]: type mismatch resolving ` as Destructure>::Destructuring == Borrow` --> tests/ui/rest_patterns_ref_only.rs:12:28 | 12 | munge!(let Struct { a, .. } = mu); | -----------------------^^-------- | | | | | expected `Borrow`, found `Move` | required by a bound introduced by this call | note: required by a bound in `only_borrow_destructuring_may_use_rest_patterns` --> src/__macro.rs | | pub fn only_borrow_destructuring_may_use_rest_patterns< | ----------------------------------------------- required by a bound in this function | T: Destructure, | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `only_borrow_destructuring_may_use_rest_patterns` error[E0271]: type mismatch resolving ` as Destructure>::Destructuring == Borrow` --> tests/ui/rest_patterns_ref_only.rs:18:25 | 18 | munge!(let Tuple(a, ..) = mu); | --------------------^^------- | | | | | expected `Borrow`, found `Move` | required by a bound introduced by this call | note: required by a bound in `only_borrow_destructuring_may_use_rest_patterns` --> src/__macro.rs | | pub fn only_borrow_destructuring_may_use_rest_patterns< | ----------------------------------------------- required by a bound in this function | T: Destructure, | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `only_borrow_destructuring_may_use_rest_patterns`