munge/
lib.rs

1//! Munge makes it easy and safe to destructure `MaybeUninit`s, `Cell`s,
2//! `UnsafeCell`s, `ManuallyDrop`s and more.
3//!
4//! Just use the `munge!` macro to destructure opaque types the same way you'd
5//! destructure a value. The `munge!` macro may be used to perform either borrow
6//! destructuring (e.g. `let (a, b) = c` where `c` is a reference) or move
7//! destructuring (e.g. `let (a, b) = c` where `c` is a value) depending on the
8//! type.
9//!
10//! Munge has no features and is always `#![no_std]`.
11//!
12//! ## Examples
13#![doc = include_str!("../example.md")]
14#![no_std]
15#![deny(
16    future_incompatible,
17    missing_docs,
18    nonstandard_style,
19    unsafe_op_in_unsafe_fn,
20    unused,
21    warnings,
22    clippy::all,
23    clippy::missing_safety_doc,
24    clippy::undocumented_unsafe_blocks,
25    rustdoc::broken_intra_doc_links,
26    rustdoc::missing_crate_level_docs
27)]
28#![cfg_attr(all(docsrs, not(doctest)), feature(doc_cfg))]
29
30#[doc(hidden)]
31pub mod __macro;
32mod impls;
33mod internal;
34
35#[doc(hidden)]
36pub use munge_macro::munge_with_path;
37
38/// Destructures a type using a pattern.
39///
40/// To prevent unsound union destructurings, this macro emits field accesses
41/// which fail to compile in safe Rust. However, if `munge!` is used inside of
42/// an `unsafe` block, these accesses will compile without emitting an error.
43/// This matches the behavior of regular destructuring, but may be surprising in
44/// some situations.
45///
46/// # Example
47///
48/// ```
49/// # use core::mem::MaybeUninit;
50/// # use munge::munge;
51/// pub struct Example {
52///     a: u32,
53///     b: (char, f32),
54/// }
55///
56/// let mut mu = MaybeUninit::<Example>::uninit();
57///
58/// munge!(let Example { a, b: (c, mut f) } = &mut mu);
59/// assert_eq!(a.write(10), &10);
60/// assert_eq!(c.write('x'), &'x');
61/// assert_eq!(f.write(3.14), &3.14);
62/// // Note that `mut` bindings can be reassigned like you'd expect:
63/// let mut new_f = MaybeUninit::uninit();
64/// f = &mut new_f;
65///
66/// // SAFETY: `mu` is completely initialized.
67/// let init = unsafe { mu.assume_init() };
68/// assert_eq!(init.a, 10);
69/// assert_eq!(init.b.0, 'x');
70/// assert_eq!(init.b.1, 3.14);
71/// ```
72#[macro_export]
73macro_rules! munge {
74    ($($t:tt)*) => { $crate::munge_with_path!($crate => $($t)*) }
75}
76
77/// A type that can be destructured into its constituent parts.
78///
79/// See the [crate docs](index.html#examples) for an example of implementing
80/// `Destructure` and `Restructure`.
81///
82/// # Safety
83///
84/// - [`Destructuring`](Destructure::Destructuring) must reflect the type of
85///   destructuring allowed for the type:
86///   - [`Borrow`] if the type is restructured by creating disjoint borrows of
87///     the fields of `Underlying`.
88///   - [`Move`] if the type may be restructured by moving the fields out of the
89///     destructured `Underlying`.
90/// - [`underlying`](Destructure::underlying) must return a pointer that is
91///   non-null, properly aligned, and valid for reads.
92pub unsafe trait Destructure: Sized {
93    /// The underlying type that is destructured.
94    type Underlying: ?Sized;
95    /// The type of destructuring to perform.
96    type Destructuring: internal::Destructuring;
97
98    /// Returns a mutable pointer to the underlying type.
99    fn underlying(&mut self) -> *mut Self::Underlying;
100}
101
102/// A type that can be "restructured" as a field of some containing type.
103///
104/// See the [crate docs](index.html#examples) for an example of implementing
105/// `Destructure` and `Restructure`.
106///
107/// # Safety
108///
109/// [`restructure`](Restructure::restructure) must return a valid
110/// [`Restructured`](Restructure::Restructured) that upholds the invariants for
111/// its [`Destructuring`](Destructure::Destructuring):
112/// - If the type is destructured [by borrow](Borrow), then the `Restructured`
113///   value must behave as a disjoint borrow of a field of the underlying type.
114/// - If the type is destructured [by move](Move), then the `Restructured` value
115///   must move the fields out of the underlying type.
116pub unsafe trait Restructure<T: ?Sized>: Destructure {
117    /// The restructured version of this type.
118    type Restructured;
119
120    /// Restructures a pointer to this type into the target type.
121    ///
122    /// # Safety
123    ///
124    /// `ptr` must be a properly aligned pointer to a subfield of the pointer
125    /// [`underlying`](Destructure::underlying) `self`.
126    unsafe fn restructure(&self, ptr: *mut T) -> Self::Restructured;
127}
128
129/// Destructuring by borrow, e.g. `let (a, b) = c` where `c` is a reference.
130///
131/// Borrow destructuring leaves the original value intact, only borrowing from
132/// the destructured value. Borrow destructuring may use rest patterns (`..`)
133/// because the original value is not moved and so it is safe to restructure
134/// only some of the fields of the destructured value.
135pub struct Borrow;
136
137impl internal::Destructuring for Borrow {}
138
139impl<T: Destructure> internal::DestructuringFor<T> for Borrow {
140    type Destructurer = internal::Borrow<T>;
141}
142
143/// Destructuring by move, e.g. `let (a, b) = c` where `c` is a value.
144///
145/// Move destructuring forgets the original value and moves each destructured
146/// field during restructuring. Move destructuring may not use rest patterns
147/// (`..`) because every field of the original value must be restructured, else
148/// they will be forgotten.
149pub struct Move;
150
151impl internal::Destructuring for Move {}
152
153impl<T: Destructure> internal::DestructuringFor<T> for Move {
154    type Destructurer = internal::Move<T>;
155}
156
157#[cfg(test)]
158mod tests {
159    use core::{cell::Cell, mem::MaybeUninit};
160
161    #[test]
162    fn project_tuple() {
163        let mut mu = MaybeUninit::<(u32, char)>::uninit();
164
165        munge!(let (a, b) = &mut mu);
166        assert_eq!(a.write(1), &1);
167        assert_eq!(b.write('a'), &'a');
168        munge!(let (a, b,) = &mut mu);
169        assert_eq!(a.write(2), &2);
170        assert_eq!(b.write('b'), &'b');
171
172        munge!(let (a, _) = &mut mu);
173        assert_eq!(a.write(3), &3);
174        munge!(let (_, b) = &mut mu);
175        assert_eq!(b.write('c'), &'c');
176        munge!(let (a, _,) = &mut mu);
177        assert_eq!(a.write(3), &3);
178        munge!(let (_, b,) = &mut mu);
179        assert_eq!(b.write('c'), &'c');
180
181        munge!(let (mut a, mut b) = &mut mu);
182        assert_eq!(a.write(4), &4);
183        assert_eq!(b.write('d'), &'d');
184        let mut new_a = MaybeUninit::uninit();
185        a = &mut new_a;
186        let mut new_b = MaybeUninit::uninit();
187        b = &mut new_b;
188        let _ = a;
189        let _ = b;
190
191        munge!(let (a, ..) = &mut mu);
192        assert_eq!(a.write(5), &5);
193
194        // SAFETY: `mu` is completely initialized.
195        let init = unsafe { mu.assume_init() };
196        assert_eq!(init.0, 5);
197        assert_eq!(init.1, 'd');
198    }
199
200    #[test]
201    fn project_array() {
202        let mut mu = MaybeUninit::<[u32; 2]>::uninit();
203
204        munge!(let [a, b] = &mut mu);
205        assert_eq!(a.write(1), &1);
206        assert_eq!(b.write(1), &1);
207        munge!(let [a, b,] = &mut mu);
208        assert_eq!(a.write(2), &2);
209        assert_eq!(b.write(2), &2);
210
211        munge!(let [a, _] = &mut mu);
212        assert_eq!(a.write(3), &3);
213        munge!(let [_, b] = &mut mu);
214        assert_eq!(b.write(3), &3);
215        munge!(let [a, _,] = &mut mu);
216        assert_eq!(a.write(4), &4);
217        munge!(let [_, b,] = &mut mu);
218        assert_eq!(b.write(4), &4);
219
220        munge!(let [mut a, mut b] = &mut mu);
221        assert_eq!(a.write(5), &5);
222        assert_eq!(b.write(5), &5);
223        let mut new_a = MaybeUninit::uninit();
224        a = &mut new_a;
225        let mut new_b = MaybeUninit::uninit();
226        b = &mut new_b;
227        let _ = a;
228        let _ = b;
229
230        munge!(let [a, ..] = &mut mu);
231        assert_eq!(a.write(6), &6);
232
233        // SAFETY: `mu` is completely initialized.
234        let init = unsafe { mu.assume_init() };
235        assert_eq!(init[0], 6);
236        assert_eq!(init[1], 5);
237    }
238
239    #[test]
240    fn project_struct() {
241        pub struct Example {
242            pub a: u32,
243            pub b: char,
244        }
245
246        let mut mu = MaybeUninit::<Example>::uninit();
247
248        munge!(let Example { a, b } = &mut mu);
249        assert_eq!(a.write(1), &1);
250        assert_eq!(b.write('a'), &'a');
251        munge!(let Example { a, b, } = &mut mu);
252        assert_eq!(a.write(2), &2);
253        assert_eq!(b.write('b'), &'b');
254
255        munge!(let Example { a, b: x } = &mut mu);
256        assert_eq!(a.write(3), &3);
257        assert_eq!(x.write('c'), &'c');
258        munge!(let Example { a, b: x, } = &mut mu);
259        assert_eq!(a.write(4), &4);
260        assert_eq!(x.write('d'), &'d');
261
262        munge!(let Example { a: x, b } = &mut mu);
263        assert_eq!(x.write(3), &3);
264        assert_eq!(b.write('c'), &'c');
265        munge!(let Example { a: x, b, } = &mut mu);
266        assert_eq!(x.write(4), &4);
267        assert_eq!(b.write('d'), &'d');
268
269        munge!(let Example { a, b: _ } = &mut mu);
270        assert_eq!(a.write(5), &5);
271        munge!(let Example { a, b: _, } = &mut mu);
272        assert_eq!(a.write(6), &6);
273
274        munge!(let Example { mut a, mut b } = &mut mu);
275        assert_eq!(a.write(7), &7);
276        assert_eq!(b.write('e'), &'e');
277        let mut new_a = MaybeUninit::uninit();
278        a = &mut new_a;
279        let mut new_b = MaybeUninit::uninit();
280        b = &mut new_b;
281        let _ = a;
282        let _ = b;
283
284        munge!(let Example { a: mut x, b: mut y } = &mut mu);
285        assert_eq!(x.write(8), &8);
286        assert_eq!(y.write('f'), &'f');
287        let mut new_x = MaybeUninit::uninit();
288        x = &mut new_x;
289        let mut new_y = MaybeUninit::uninit();
290        y = &mut new_y;
291        let _ = x;
292        let _ = y;
293
294        munge!(let Example { b, .. } = &mut mu);
295        assert_eq!(b.write('g'), &'g');
296
297        // SAFETY: `mu` is completely initialized.
298        let init = unsafe { mu.assume_init() };
299        assert_eq!(init.a, 8);
300        assert_eq!(init.b, 'g');
301    }
302
303    #[test]
304    fn project_tuple_struct() {
305        struct Example(u32, char);
306
307        let mut mu = MaybeUninit::<Example>::uninit();
308
309        munge!(let Example(a, b) = &mut mu);
310        assert_eq!(a.write(1), &1);
311        assert_eq!(b.write('a'), &'a');
312        munge!(let Example(a, b,) = &mut mu);
313        assert_eq!(a.write(2), &2);
314        assert_eq!(b.write('b'), &'b');
315
316        munge!(let Example(a, _) = &mut mu);
317        assert_eq!(a.write(3), &3);
318        munge!(let Example(_, b) = &mut mu);
319        assert_eq!(b.write('c'), &'c');
320        munge!(let Example(a, _,) = &mut mu);
321        assert_eq!(a.write(3), &3);
322        munge!(let Example(_, b,) = &mut mu);
323        assert_eq!(b.write('d'), &'d');
324
325        munge!(let Example(mut a, mut b) = &mut mu);
326        assert_eq!(a.write(4), &4);
327        assert_eq!(b.write('e'), &'e');
328        let mut new_a = MaybeUninit::uninit();
329        a = &mut new_a;
330        let mut new_b = MaybeUninit::uninit();
331        b = &mut new_b;
332        let _ = a;
333        let _ = b;
334
335        munge!(let Example(a, ..) = &mut mu);
336        assert_eq!(a.write(5), &5);
337
338        // SAFETY: `mu` is completely initialized.
339        let init = unsafe { mu.assume_init() };
340        assert_eq!(init.0, 5);
341        assert_eq!(init.1, 'e');
342    }
343
344    #[test]
345    fn project_generic() {
346        struct Example<T>(u32, T);
347
348        let mut mu = MaybeUninit::<Example<char>>::uninit();
349
350        munge!(let Example(a, b) = &mut mu);
351        assert_eq!(a.write(1), &1);
352        assert_eq!(b.write('a'), &'a');
353        munge!(let Example(a, b,) = &mut mu);
354        assert_eq!(a.write(2), &2);
355        assert_eq!(b.write('b'), &'b');
356
357        munge!(let Example(a, _) = &mut mu);
358        assert_eq!(a.write(3), &3);
359        munge!(let Example(_, b) = &mut mu);
360        assert_eq!(b.write('c'), &'c');
361        munge!(let Example(a, _,) = &mut mu);
362        assert_eq!(a.write(3), &3);
363        munge!(let Example(_, b,) = &mut mu);
364        assert_eq!(b.write('c'), &'c');
365
366        munge!(let Example(a, ..) = &mut mu);
367        assert_eq!(a.write(4), &4);
368
369        // SAFETY: `mu` is completely initialized.
370        let init = unsafe { mu.assume_init() };
371        assert_eq!(init.0, 4);
372        assert_eq!(init.1, 'c');
373
374        let mut mu = MaybeUninit::<Example<Example<char>>>::uninit();
375
376        munge!(
377            let Example::<Example<char>>(a, Example::<char>(b, c)) = &mut mu;
378        );
379        assert_eq!(a.write(1), &1);
380        assert_eq!(b.write(2), &2);
381        assert_eq!(c.write('a'), &'a');
382
383        // SAFETY: `mu` is completely initialized.
384        let init = unsafe { mu.assume_init() };
385        assert_eq!(init.0, 1);
386        assert_eq!(init.1 .0, 2);
387        assert_eq!(init.1 .1, 'a');
388    }
389
390    #[test]
391    fn project_nested_struct() {
392        struct Inner {
393            a: u32,
394            b: char,
395        }
396        struct Outer {
397            inner: Inner,
398            c: i32,
399        }
400
401        let mut mu = MaybeUninit::<Outer>::uninit();
402
403        munge!(let Outer { inner: Inner { a, b }, c } = &mut mu);
404        assert_eq!(a.write(1), &1);
405        assert_eq!(b.write('a'), &'a');
406        assert_eq!(c.write(2), &2);
407
408        // SAFETY: `mu` is completely initialized.
409        let init = unsafe { mu.assume_init() };
410        assert_eq!(init.inner.a, 1);
411        assert_eq!(init.inner.b, 'a');
412        assert_eq!(init.c, 2);
413    }
414
415    #[test]
416    fn project_nested_tuple() {
417        let mut mu = MaybeUninit::<(u32, (char, u32))>::uninit();
418
419        munge!(let (a, (b, c)) = &mut mu);
420        assert_eq!(a.write(1), &1);
421        assert_eq!(b.write('a'), &'a');
422        assert_eq!(c.write(2), &2);
423
424        // SAFETY: `mu` is completely initialized.
425        let init = unsafe { mu.assume_init() };
426        assert_eq!(init, (1, ('a', 2)));
427    }
428
429    #[test]
430    fn project_nested_array() {
431        let mut mu = MaybeUninit::<[[u32; 2]; 2]>::uninit();
432
433        munge!(let [a, [b, c]] = &mut mu);
434        assert_eq!(a.write([1, 2]), &[1, 2]);
435        assert_eq!(b.write(3), &3);
436        assert_eq!(c.write(4), &4);
437
438        // SAFETY: `mu` is completely initialized.
439        let init = unsafe { mu.assume_init() };
440        assert_eq!(init, [[1, 2], [3, 4]]);
441    }
442
443    #[test]
444    fn generics() {
445        struct Inner<T> {
446            a: u32,
447            b: T,
448        }
449        struct Outer<T> {
450            inner: Inner<T>,
451            c: i32,
452        }
453
454        let mut mu = MaybeUninit::<Outer<char>>::uninit();
455
456        munge!(let Outer { inner: Inner { a, b }, c } = &mut mu);
457        assert_eq!(a.write(1), &1);
458        assert_eq!(b.write('a'), &'a');
459        assert_eq!(c.write(2), &2);
460
461        // SAFETY: `mu` is completely initialized.
462        let init = unsafe { mu.assume_init() };
463        assert_eq!(init.inner.a, 1);
464        assert_eq!(init.inner.b, 'a');
465        assert_eq!(init.c, 2);
466    }
467
468    #[test]
469    fn cell() {
470        use core::cell::Cell;
471
472        pub struct Example {
473            a: u32,
474            b: (char, f32),
475        }
476
477        let value = Example {
478            a: 10,
479            b: ('x', core::f32::consts::PI),
480        };
481        let cell = Cell::<Example>::new(value);
482
483        munge!(let Example { a, b: (c, f) } = &cell);
484        assert_eq!(a.get(), 10);
485        a.set(42);
486        assert_eq!(c.get(), 'x');
487        c.set('!');
488        assert_eq!(f.get(), core::f32::consts::PI);
489        f.set(1.41);
490
491        let value = cell.into_inner();
492        assert_eq!(value.a, 42);
493        assert_eq!(value.b.0, '!');
494        assert_eq!(value.b.1, 1.41);
495    }
496
497    #[test]
498    fn maybe_uninit_value() {
499        let mu = MaybeUninit::<(u32, char)>::new((10_000, 'x'));
500
501        munge!(let (a, b) = mu);
502        assert_eq!(unsafe { a.assume_init() }, 10_000);
503        assert_eq!(unsafe { b.assume_init() }, 'x');
504    }
505
506    #[test]
507    fn cell_value() {
508        use core::cell::Cell;
509
510        let cell = Cell::<(u32, char)>::new((10_000, 'x'));
511
512        munge!(let (a, b) = cell);
513        assert_eq!(a.get(), 10_000);
514        assert_eq!(b.get(), 'x');
515    }
516
517    #[test]
518    fn unsafe_cell_value() {
519        use core::cell::UnsafeCell;
520
521        let uc = UnsafeCell::<(u32, char)>::new((10_000, 'x'));
522
523        munge!(let (mut a, mut b) = uc);
524        assert_eq!(*a.get_mut(), 10_000);
525        assert_eq!(*b.get_mut(), 'x');
526    }
527
528    #[test]
529    fn manually_drop_value() {
530        use core::mem::ManuallyDrop;
531
532        let md = ManuallyDrop::new((10_000, 'x'));
533
534        munge!(let (a, b) = md);
535        assert_eq!(*a, 10_000);
536        assert_eq!(*b, 'x');
537    }
538
539    #[test]
540    fn struct_borrow_partial_destructuring() {
541        use core::cell::Cell;
542
543        struct Example {
544            a: u32,
545            b: u32,
546        }
547
548        let mut value = Cell::new(Example { a: 0, b: 1 });
549
550        munge!(let Example { a, .. } = &mut value);
551        assert_eq!(a.get(), 0);
552        a.set(2);
553        assert_eq!(a.get(), 2);
554
555        munge!(let Example { a: c, b: _ } = &value);
556        assert_eq!(c.get(), 2);
557        c.set(3);
558        assert_eq!(c.get(), 3);
559    }
560
561    #[test]
562    fn tuple_borrow_partial_destructuring() {
563        use core::cell::Cell;
564
565        struct Example(u32, u32);
566
567        let mut value = Cell::new(Example(0, 1));
568
569        munge!(let Example(a, ..) = &mut value);
570        assert_eq!(a.get(), 0);
571        a.set(2);
572        assert_eq!(a.get(), 2);
573
574        munge!(let Example(c, _) = &value);
575        assert_eq!(c.get(), 2);
576        c.set(3);
577        assert_eq!(c.get(), 3);
578    }
579
580    struct NoisyDrop<'a> {
581        flag: &'a mut bool,
582    }
583
584    impl Drop for NoisyDrop<'_> {
585        fn drop(&mut self) {
586            *self.flag = true;
587        }
588    }
589
590    #[test]
591    fn moved_tuple_wildcard_pattern_is_dropped() {
592        let mut flag = false;
593        let value = Cell::new((NoisyDrop { flag: &mut flag },));
594
595        munge!(let (_,) = value);
596
597        assert!(flag);
598    }
599
600    #[test]
601    fn moved_tuple_struct_wildcard_pattern_is_dropped() {
602        struct Example<'a>(NoisyDrop<'a>);
603
604        let mut flag = false;
605        let value = Cell::new(Example(NoisyDrop { flag: &mut flag }));
606
607        munge!(let Example(_) = value);
608
609        assert!(flag);
610    }
611
612    #[test]
613    fn moved_array_wildcard_pattern_is_dropped() {
614        let mut flag = false;
615        let value = Cell::new([NoisyDrop { flag: &mut flag }]);
616
617        munge!(let [_] = value);
618
619        assert!(flag);
620    }
621
622    #[test]
623    fn rest_in_full_tuple_pattern() {
624        let (_, _, ..) = (1, 2);
625
626        let value = Cell::new((1, 2));
627        munge!(let (_, _, ..) = &value);
628
629        let [_, _, ..] = [1, 2];
630
631        let value = Cell::new([1, 2]);
632        munge!(let [_, _, ..] = &value);
633
634        struct Foo(i32, i32);
635
636        let Foo(_, _, ..) = Foo(1, 2);
637
638        let value = Cell::new(Foo(1, 2));
639        munge!(let Foo(_, _, ..) = &value);
640
641        struct Bar {
642            a: i32,
643            b: i32,
644        }
645
646        let Bar { a: _, b: _, .. } = Bar { a: 1, b: 2 };
647
648        let value = Cell::new(Bar { a: 1, b: 2 });
649        munge!(let Bar { a: _, b: _, .. } = &value);
650    }
651}