1#![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#[macro_export]
73macro_rules! munge {
74 ($($t:tt)*) => { $crate::munge_with_path!($crate => $($t)*) }
75}
76
77pub unsafe trait Destructure: Sized {
93 type Underlying: ?Sized;
95 type Destructuring: internal::Destructuring;
97
98 fn underlying(&mut self) -> *mut Self::Underlying;
100}
101
102pub unsafe trait Restructure<T: ?Sized>: Destructure {
117 type Restructured;
119
120 unsafe fn restructure(&self, ptr: *mut T) -> Self::Restructured;
127}
128
129pub 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
143pub 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 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 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 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 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 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 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 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 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 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 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}