konst/macros/
destructuring.rs1#![expect(non_camel_case_types)]
2#![expect(clippy::empty_loop)]
3
4use core::marker::PhantomData;
5use core::mem::ManuallyDrop;
6
7#[doc(hidden)]
10pub trait __GetImplsHelper {
11 type T: ?Sized;
12
13 fn __impls_drop_iwrhqlpnnieu8c6w(&self) -> __DoesNotImplDrop<Self::T>;
14}
15
16#[doc(hidden)]
19pub struct __ImplsDrop<T: ?Sized>(PhantomData<fn(T) -> T>);
20
21#[doc(hidden)]
24pub struct __DoesNotImplDrop<T: ?Sized>(PhantomData<fn(T) -> T>);
25
26impl<T: ?Sized> __DoesNotImplDrop<T> {
27 pub const fn new(_: *mut T) -> Self {
28 Self(PhantomData)
29 }
30}
31
32#[doc(hidden)]
35pub struct __GetImpls_IWRHQLPNNIEU8C6W<T: ?Sized>(pub PhantomData<fn(T) -> T>);
36
37impl<T> __GetImplsHelper for __GetImpls_IWRHQLPNNIEU8C6W<T> {
38 type T = T;
39
40 fn __impls_drop_iwrhqlpnnieu8c6w(&self) -> __DoesNotImplDrop<Self::T> {
41 __DoesNotImplDrop(PhantomData)
42 }
43}
44
45#[expect(drop_bounds)]
46impl<T> __GetImpls_IWRHQLPNNIEU8C6W<T>
47where
48 T: Drop,
51{
52 pub fn __impls_drop_iwrhqlpnnieu8c6w(self) -> __ImplsDrop<T> {
53 __ImplsDrop(PhantomData)
54 }
55}
56
57#[doc(hidden)]
60#[inline(always)]
61pub const fn cast_manuallydrop_ptr<T>(ptr: *mut ManuallyDrop<T>) -> *mut T {
62 ptr.cast()
63}
64
65#[doc(hidden)]
66#[inline(always)]
67pub const fn cast_manuallydrop_array_ptr<T, const N: usize>(
69 ptr: *mut ManuallyDrop<[T; N]>,
70) -> *mut T {
71 ptr.cast()
72}
73
74#[doc(hidden)]
75#[inline(always)]
76pub const fn cast_ptr_with_phantom<T, U>(ptr: *mut T, _phantom: PhantomData<fn(U) -> U>) -> *mut U {
77 ptr.cast()
78}
79
80#[doc(hidden)]
81#[inline(always)]
82pub const fn get_phantom_len<T, const N: usize>(
83 _phantom: PhantomData<fn([T; N]) -> [T; N]>,
84) -> usize {
85 N
86}
87
88#[doc(hidden)]
89#[inline(always)]
90pub const fn make_it<T>() -> T {
91 loop {}
92}
93
94#[doc(hidden)]
95#[inline(always)]
96pub const fn fake_read<T>(_: *mut T) -> T {
97 loop {}
98}
99
100#[doc(hidden)]
101#[inline(always)]
102pub const fn make_phantom<T>(_: *mut T) -> PhantomData<fn(T) -> T> {
103 PhantomData
104}
105
106#[doc(hidden)]
107#[inline(always)]
108pub const fn array_into_phantom<T, const N: usize>(
109 val: [T; N],
110) -> PhantomData<fn([T; N]) -> [T; N]> {
111 core::mem::forget(val);
112 PhantomData
113}
114
115#[doc(hidden)]
116#[inline(always)]
117pub const fn assert_same_type<T>(this: T, that: T) {
118 core::mem::forget(this);
119 core::mem::forget(that);
120}
121
122#[doc(hidden)]
125pub type __ArrayManuallyDrop<T, const LEN: usize> = ManuallyDrop<[T; LEN]>;
126
127#[macro_export]
315macro_rules! destructure {
316 ($($(@$is_path:tt)? ::)? $($path:ident)::+ $(,)?{$($braced:tt)*} $($rem:tt)*) => (
318 $crate::__destructure__braced_struct_prepare_fields! {
319 {$($braced)*}
320 ($($(@$is_path)? ::)? $($path)::*)
321 path
322 $($rem)*
323 }
324 );
325
326 ($($(@$is_path:tt)? ::)? $($path:ident)::+ $(,)? ($($tupled:tt)*) $($rem:tt)*) => (
328 $crate::__destructure__tuple_struct_field_names!{
329 (
330 ($($(@$is_path)? ::)? $($path)::+)
331 path
332 $($rem)*
333 )
334 ()
335 ($($tupled)*)
336 (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
337 }
338 );
339
340 ($struct_path:path $(,)? {$($braced:tt)*} $($rem:tt)*) => (
342 $crate::__destructure__braced_struct_prepare_fields! {
343 {$($braced)*}
344 ($struct_path)
345 type
346 $($rem)*
347 }
348 );
349
350 ($struct_path:path, ($($tupled:tt)*) $($rem:tt)*) => (
352 $crate::__destructure__tuple_struct_field_names!{
353 (
354 ($struct_path)
355 type
356 $($rem)*
357 )
358 ()
359 ($($tupled)*)
360 (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
361 }
362 );
363
364 (() $(:$tuple_ty:ty)? = $val:expr) => (
366 let () $(: $tuple_ty)? = $val;
367 );
368 (($($tupled:tt)*) $($rem:tt)*) => (
369 $crate::__destructure__tuple_field_names!{
370 ($($rem)*)
371 ()
372 ($($tupled)*)
373 (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
374 }
375 );
376
377 ([] $(:$array_ty:ty)? = $val:expr) => (
379 let [] $(: $array_ty)? = $val;
380 );
381
382 (
383 [$( $pat:tt $(@ $dotdot:tt)? ),* $(,)?]
384
385 $($rem:tt)*
386 ) => (
387 $crate::__destructure_array__process_fields!{
388 [$( ($pat) ($($dotdot $dotdot)?) ,)*]
389
390 $($rem)*
391 }
392 );
393}
394
395#[doc(hidden)]
396#[macro_export]
397macro_rules! __destructure__braced_struct_prepare_fields {
398 (
399 {$($field:tt $(: $pattern:pat)?),* $(,)?}
400 $($rem:tt)*
401 ) => {
402 $crate::__destructure_struct!{
403 {$(($field) $field $(: $pattern)?,)*}
404
405 $($rem)*
406 }
407 }
408}
409
410#[doc(hidden)]
411#[macro_export]
412macro_rules! __destructure__tuple_struct_field_names {
413 (($($rem:tt)*) ($($patterns:tt)*) () ($($fnames:tt)*)) => {
414 $crate::__destructure_struct!{
415 {$($patterns)*}
416 $($rem)*
417 }
418 };
419 ($fixed:tt $prev_patterns:tt (.. $($next_pattern:tt)*) $fnames:tt) => {
420 $crate::__::compile_error!{
421 "`..` patterns are not supported in top-level tuple struct patterns"
422 }
423 };
424 (
425 $fixed:tt
426 ($($prev_patterns:tt)*)
427 ($pattern:pat $(, $($next_pattern:tt)*)?)
428 ($fname:tt $($next_fnames:tt)*)
429 ) => {
430 $crate::__destructure__tuple_struct_field_names!{
431 $fixed
432 ($($prev_patterns)* ($fname) $fname:$pattern,)
433 ($($($next_pattern)*)?)
434 ($($next_fnames)*)
435 }
436 };
437}
438
439#[doc(hidden)]
440#[macro_export]
441macro_rules! __destructure_struct {
442 (
443 { $(,)? }
444 ($($struct_path:tt)*)
445 $path_kind:ident
446 $(:$struct_ty:ty)?
447 = $val:expr
448 ) => (
449 let $($struct_path)* {} $(: $struct_ty)? = $val;
450 );
451 (
452 {
453 $(($($_fa0:ident)? $($_fa1:literal)?) $field:tt $(: $pattern:pat)?),*
454 $(,)?
455 }
456 ($($struct_path:tt)*)
457 $path_kind:ident
458 $(:$struct_ty:ty)?
459 = $val:expr
460 ) => (
461 let val @ $($struct_path)* {$($field: _),*} $(: $struct_ty)? = $val;
463
464 $crate::__destructuring__type_assert!{($path_kind $($struct_path)*) val}
474
475 let mut val = $crate::__::ManuallyDrop::new(val);
476
477 let ptr: *mut _ = $crate::macros::destructuring::cast_manuallydrop_ptr(&raw mut val);
478
479
480 if false {
481 _ = ||{
482 use $crate::macros::destructuring::__GetImplsHelper as _;
483
484 let _assertion_expected: $crate::macros::destructuring::__DoesNotImplDrop<_> =
487 if false {
488 $crate::macros::destructuring::__DoesNotImplDrop::new(ptr)
489 } else {
490 let assertion = $crate::macros
491 ::destructuring
492 ::__GetImpls_IWRHQLPNNIEU8C6W(
493 $crate::macros::destructuring::make_phantom(ptr)
494 ).__impls_drop_iwrhqlpnnieu8c6w();
495
496 assertion
497 };
498 };
499 }
500
501
502 $(
503 let $crate::__first_pat!( $($pattern,)? $field, ) = unsafe {
508 $crate::__::ptr::read_unaligned(&raw mut (*ptr).$field)
509 };
510 )*
511 );
512 (
513 {
514 $(($($_fa0:ident)? $($_fa1:literal)?) $field0:tt $(: $_0:pat)? ,)*
515 $(
516 (..) $field1:tt $(: $_1:pat)? ,
517 $($__anything:tt)*
518 )?
519 }
520 $($_3:tt)*
521 ) => (
522 compile_error!{"`..` patterns are not supported in top-level struct patterns"}
523 )
524}
525
526#[doc(hidden)]
527#[macro_export]
528macro_rules! __destructuring__type_assert {
529 ((path $($path:tt)*) $variable:ident) => {
530 #[allow(unreachable_code)]
532 if false {
533 loop {}
534
535 let expected @ $($path)* {..};
536
537 $crate::macros::destructuring::assert_same_type(expected, $variable)
538 }
539 };
540 ((type $type:ty) $variable:ident) => {
541 let _: $type = $variable;
542 };
543}
544
545#[doc(hidden)]
546#[macro_export]
547macro_rules! __destructure__tuple_field_names {
548 (($($rem:tt)*) ($($patterns:tt)*) () ($($fnames:tt)*)) => {
549 $crate::__destructure_tuple!{($($patterns)*) $($rem)*}
550 };
551 ($fixed:tt $prev_patterns:tt (.. $($next_pattern:tt)*) $fnames:tt) => {
552 $crate::__::compile_error!{"`..` patterns are not supported in top-level tuple patterns"}
553 };
554 (
555 $fixed:tt
556 ($($prev_patterns:tt)*)
557 ($pattern:pat $(, $($next_pattern:tt)*)?)
558 ($fname:tt $($next_fnames:tt)*)
559 ) => {
560 $crate::__destructure__tuple_field_names!{
561 $fixed
562 ($($prev_patterns)* $fname:$pattern,)
563 ($($($next_pattern)*)?)
564 ($($next_fnames)*)
565 }
566 };
567}
568
569#[doc(hidden)]
570#[macro_export]
571macro_rules! __destructure_tuple {
572 (($($field:tt: $pattern:pat,)*) $(:$tuple_ty:ty)? = $val:expr) => (
573
574 let val @ ($($crate::__first_pat!(_, $field),)*)
580 : $crate::__first_ty!($($tuple_ty,)? ($($crate::__first_ty!(_, $field),)*),)
581 = $val;
582
583 #[allow(unreachable_code)]
585 if false {
586 loop {}
587
588 let expected @ ($($crate::__first_pat!(_, $field),)*);
589
590 $crate::macros::destructuring::assert_same_type(expected, val)
591 }
592
593 let mut val = $crate::__::ManuallyDrop::new(val);
594
595 let ptr = $crate::macros::destructuring::cast_manuallydrop_ptr(&raw mut val);
596
597 $(
598 let $pattern = unsafe { $crate::__::ptr::read(&raw mut (*ptr).$field) };
601 )*
602 )
603}
604
605#[doc(hidden)]
606#[macro_export]
607macro_rules! __destructure_array__process_fields {
608 (
609 [$(
610 (
611 $( _ $($is_underscore:lifetime)? )?
612 $( $ident:ident)?
613 $( ($parenthesized:pat) )?
614 $( .. $($has_rem_elems1:lifetime)? )?
615 )
616 ($(.. $rem_elems:tt $($has_rem_elems2:lifetime)?)?),
617 )*]
618
619 $($rem:tt)*
620 ) => {
621 $crate::__destructure_array! {
622 [$(
623 (
624 (
625 $(rem $($has_rem_elems1)?)?
626 $(rem $($has_rem_elems2)?)?
627 elem
628 )
629
630 $(_ $($is_underscore)?)?
631 $(_ $($has_rem_elems1)?)?
632 $( $ident )?
633 $( $parenthesized )?
634 )
635 )*]
636
637 $($rem)*
638 }
639 }
640}
641
642#[doc(hidden)]
643#[macro_export]
644macro_rules! __destructure_array {
645 (
646 [
647 $( ((elem $($__0:tt)*) $pat_prefix:tt) )*
648 $(
649 ((rem $($__1:tt)*) $pat_rem:tt)
650
651 $( ((elem $($__2:tt)*) $pat_suffix:tt) )*
652 )?
653 ]
654
655 $(:$array_ty:ty)?
656 = $val:expr
657 ) => {
658 let array $(: $array_ty)? = $val;
659
660 $( let $crate::__first_pat!(rem_ty_phantom, $pat_rem) = $crate::__::PhantomData; )?
661
662 #[allow(unreachable_code)]
665 if false {
666 loop {}
667
668 _ = $crate::macros::destructuring::array_into_phantom(array);
670
671 let [
672 $($crate::__first_pat!(_, $pat_prefix),)*
673 $(
674 $crate::__first_pat!(rem @ .., $pat_rem),
675 $($crate::__first_pat!(_, $pat_suffix),)*
676 )?
677 ] = array;
678
679 $(
680 rem_ty_phantom = $crate::macros::destructuring::array_into_phantom(
681 $crate::__first_expr!(rem, $pat_rem)
682 );
683 )?
684
685 }
686
687 let mut array = $crate::macros::destructuring::__ArrayManuallyDrop::new(array);
688
689 let ptr = $crate::macros::destructuring::cast_manuallydrop_array_ptr(&raw mut array);
690 let mut i = 0;
691
692
693 $crate::__destructure_array__read_elems!{unsafe, ptr, i, [$($pat_prefix),*]}
694
695 $(
696
697 let $pat_rem = unsafe {
700 let rem_ptr = $crate::macros::destructuring::cast_ptr_with_phantom(
701 <*mut _>::add(ptr, i),
702 rem_ty_phantom,
703 );
704
705 $crate::__::ptr::read(rem_ptr)
706 };
707
708 i += $crate::macros::destructuring::get_phantom_len(rem_ty_phantom);
709
710
711 $crate::__destructure_array__read_elems!{unsafe, ptr, i, [$($pat_suffix),*]}
712 )?
713 }
714}
715
716#[doc(hidden)]
717#[macro_export]
718macro_rules! __destructure_array__read_elems {
719 ($unsafe:ident, $ptr:ident, $i:ident, [$($pattern:pat),*]) => {
720 $(
721 let $pattern = $unsafe { $crate::__::ptr::read(<*mut _>::add($ptr, $i)) };
724
725 $i += 1;
726 )*
727 }
728}
729
730#[macro_export]
731#[doc(hidden)]
732macro_rules! __first_pat {
733 ($first:pat, $($rem:tt)* ) => {
734 $first
735 };
736}
737
738#[macro_export]
739#[doc(hidden)]
740macro_rules! __first_ty {
741 ($first:ty, $($rem:tt)* ) => {
742 $first
743 };
744}
745
746#[macro_export]
747#[doc(hidden)]
748macro_rules! __first_expr {
749 ($first:expr, $($rem:tt)* ) => {
750 $first
751 };
752}