1use core::mem::MaybeUninit;
2
3use crate::Const;
4use generic_upper_bound as gub;
5
6mod gen {
7 include!(concat!(env!("OUT_DIR"), "/for_each_align.rs"));
8 pub(crate) use for_each_align;
9}
10pub(crate) use gen::for_each_align;
11
12pub const unsafe fn promote<'a, C: Const>() -> &'a C::Type {
40 unsafe { &*core::ptr::from_ref(gub::eval_with_upper_bound::<Promote<C>>()).cast() }
46}
47
48trait Anything {}
49impl<T> Anything for T {}
50
51struct Promote<C>(C);
52impl<C: Const> gub::AcceptUpperBound for Promote<C> {
53 type Output = &'static dyn Anything;
54 const DESIRED_GENERIC: usize = size_of::<C::Type>();
55 type Eval<const UPPER: usize> = PromoteSized<C, UPPER>;
56}
57
58#[repr(C)]
59struct AlignedBuf<Aligner, const SIZE: usize>([MaybeUninit<u8>; SIZE], Aligner);
60
61struct PromoteSized<C, const SIZE: usize>(C);
62impl<C: Const, const SIZE: usize> Const for PromoteSized<C, SIZE> {
63 type Type = &'static dyn Anything;
64 const VALUE: Self::Type = if gub::get_upper_bound::<Promote<C>>() == SIZE {
65 const fn const_to_buf<C: Const, const SIZE: usize>() -> [MaybeUninit<u8>; SIZE] {
66 use core::mem::ManuallyDrop;
67
68 #[repr(C)]
69 union Transmute<T, const SIZE: usize> {
70 val: ManuallyDrop<T>,
71 buf: [MaybeUninit<u8>; SIZE],
72 }
73
74 unsafe {
77 Transmute {
78 val: ManuallyDrop::new(crate::value_of::<C>()),
79 }
80 .buf
81 }
82 }
83 macro_rules! handle_aligns {
84 ($($align:literal)*) => {
85 $(if align_of::<C::Type>() == $align {
86 #[repr(align($align))]
87 struct Aligner;
88 &AlignedBuf(const_to_buf::<C, SIZE>(), Aligner)
89 } else )* {
90 panic!("Unknown alignment")
91 }
92 };
93 }
94 for_each_align!(handle_aligns)
95 } else {
96 &()
97 };
98}
99
100#[test]
101fn promote_adt() {
102 #[repr(align(256))]
103 #[derive(PartialEq, Eq, Debug)]
104 struct Inner([u32; 3]);
105
106 #[repr(C)]
107 #[derive(PartialEq, Eq, Debug)]
108 struct Composite {
109 f: Option<[fn() -> i32; 3]>,
110 a: Inner,
111 r: &'static u32,
112 p: *const u32,
113 b: bool,
114 }
115
116 fn f<const N: i32>() -> i32 {
117 N
118 }
119
120 struct Value;
121 impl Const for Value {
122 type Type = Composite;
123 const VALUE: Self::Type = Composite {
124 f: Some([f::<1>, f::<420>, f::<13>]),
125 a: Inner([3, 2, 1]),
126 r: &1,
127 p: std::ptr::without_provenance(42),
128 b: true,
129 };
130 }
131
132 let promoted = unsafe { promote::<Value>() };
135
136 assert_eq!(&Value::VALUE, promoted);
137}