Skip to content

Commit 1e4a857

Browse files
asahilinametaspace
authored andcommitted
driver, of: Mangle the device ID machinery further to remove const_trait_impl
This unstable feature is broken/gone in 1.73. To work around this without breaking the API, turn IdArray::new() into a macro so that it can use concrete types (which can still have const associated functions) instead of a trait. This is quite ugly... Signed-off-by: Asahi Lina <[email protected]>
1 parent f2290d8 commit 1e4a857

File tree

2 files changed

+85
-36
lines changed

2 files changed

+85
-36
lines changed

rust/kernel/driver.rs

Lines changed: 85 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ impl<T: DriverOps> Drop for Registration<T> {
119119
/// - [`RawDeviceId::ZERO`] is actually a zeroed-out version of the raw device id.
120120
/// - [`RawDeviceId::to_rawid`] stores `offset` in the context/data field of the raw device id so
121121
/// that buses can recover the pointer to the data.
122-
#[const_trait]
123122
pub unsafe trait RawDeviceId {
124123
/// The raw type that holds the device id.
125124
///
@@ -131,13 +130,6 @@ pub unsafe trait RawDeviceId {
131130
/// Id tables created from [`Self`] use [`Self::ZERO`] as the sentinel to indicate the end of
132131
/// the table.
133132
const ZERO: Self::RawType;
134-
135-
/// Converts an id into a raw id.
136-
///
137-
/// `offset` is the offset from the memory location where the raw device id is stored to the
138-
/// location where its associated context information is stored. Implementations must store
139-
/// this in the appropriate context/data field of the raw type.
140-
fn to_rawid(&self, offset: isize) -> Self::RawType;
141133
}
142134

143135
/// A zero-terminated device id array, followed by context data.
@@ -149,44 +141,102 @@ pub struct IdArray<T: RawDeviceId, U, const N: usize> {
149141
}
150142

151143
impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
144+
const U_NONE: Option<U> = None;
145+
146+
/// Returns an `IdTable` backed by `self`.
147+
///
148+
/// This is used to essentially erase the array size.
149+
pub const fn as_table(&self) -> IdTable<'_, T, U> {
150+
IdTable {
151+
first: &self.ids[0],
152+
_p: PhantomData,
153+
}
154+
}
155+
156+
/// Returns the number of items in the ID table.
157+
pub const fn count(&self) -> usize {
158+
self.ids.len()
159+
}
160+
161+
/// Returns the inner IdArray array, without the context data.
162+
// pub const fn as_ids(&self) -> IdArrayIds<T, N>
163+
// where
164+
// T: RawDeviceId + Copy,
165+
// {
166+
// self.ids
167+
// }
168+
152169
/// Creates a new instance of the array.
153170
///
154171
/// The contents are derived from the given identifiers and context information.
155-
pub const fn new(ids: [T; N], infos: [Option<U>; N]) -> Self
172+
#[doc(hidden)]
173+
pub const unsafe fn new(raw_ids: [T::RawType; N], infos: [Option<U>; N]) -> Self
156174
where
157-
T: ~const RawDeviceId + Copy,
175+
T: RawDeviceId + Copy,
176+
T::RawType: Copy + Clone,
158177
{
159-
let mut array = Self {
160-
ids: [T::ZERO; N],
178+
Self {
179+
ids: raw_ids,
161180
sentinel: T::ZERO,
162181
id_infos: infos,
163-
};
164-
let mut i = 0usize;
165-
while i < N {
166-
// SAFETY: Both pointers are within `array` (or one byte beyond), consequently they are
167-
// derived from the same allocated object. We are using a `u8` pointer, whose size 1,
168-
// so the pointers are necessarily 1-byte aligned.
169-
let offset = unsafe {
170-
(&array.id_infos[i] as *const _ as *const u8)
171-
.offset_from(&array.ids[i] as *const _ as _)
172-
};
173-
array.ids[i] = ids[i].to_rawid(offset);
174-
i += 1;
175182
}
176-
array
177183
}
178184

179-
/// Returns an `IdTable` backed by `self`.
180-
///
181-
/// This is used to essentially erase the array size.
182-
pub const fn as_table(&self) -> IdTable<'_, T, U> {
183-
IdTable {
184-
first: &self.ids[0],
185-
_p: PhantomData,
186-
}
185+
#[doc(hidden)]
186+
pub const fn get_offset(idx: usize) -> isize
187+
where
188+
T: RawDeviceId + Copy,
189+
T::RawType: Copy + Clone,
190+
{
191+
// SAFETY: We are only using this dummy value to get offsets.
192+
let array = unsafe { Self::new([T::ZERO; N], [Self::U_NONE; N]) };
193+
// SAFETY: Both pointers are within `array` (or one byte beyond), consequently they are
194+
// derived from the same allocated object. We are using a `u8` pointer, whose size 1,
195+
// so the pointers are necessarily 1-byte aligned.
196+
let ret = unsafe {
197+
(&array.id_infos[idx] as *const _ as *const u8)
198+
.offset_from(&array.ids[idx] as *const _ as _)
199+
};
200+
core::mem::forget(array);
201+
ret
187202
}
188203
}
189204

205+
// Creates a new ID array. This is a macro so it can take as a parameter the concrete ID type in order
206+
// to call to_rawid() on it, and still remain const. This is necessary until a new const_trait_impl
207+
// implementation lands, since the existing implementation was removed in Rust 1.73.
208+
#[macro_export]
209+
#[doc(hidden)]
210+
macro_rules! _new_id_array {
211+
(($($args:tt)*), $id_type:ty) => {{
212+
/// Creates a new instance of the array.
213+
///
214+
/// The contents are derived from the given identifiers and context information.
215+
const fn new< U, const N: usize>(ids: [$id_type; N], infos: [Option<U>; N])
216+
-> $crate::driver::IdArray<$id_type, U, N>
217+
where
218+
$id_type: $crate::driver::RawDeviceId + Copy,
219+
<$id_type as $crate::driver::RawDeviceId>::RawType: Copy + Clone,
220+
{
221+
let mut raw_ids =
222+
[<$id_type as $crate::driver::RawDeviceId>::ZERO; N];
223+
let mut i = 0usize;
224+
while i < N {
225+
let offset: isize = $crate::driver::IdArray::<$id_type, U, N>::get_offset(i);
226+
raw_ids[i] = ids[i].to_rawid(offset);
227+
i += 1;
228+
}
229+
230+
// SAFETY: We are passing valid arguments computed with the correct offsets.
231+
unsafe {
232+
$crate::driver::IdArray::<$id_type, U, N>::new(raw_ids, infos)
233+
}
234+
}
235+
236+
new($($args)*)
237+
}}
238+
}
239+
190240
/// A device id table.
191241
///
192242
/// The table is guaranteed to be zero-terminated and to be followed by an array of context data of
@@ -337,8 +387,8 @@ macro_rules! define_id_array {
337387
($table_name:ident, $id_type:ty, $data_type:ty, [ $($t:tt)* ]) => {
338388
const $table_name:
339389
$crate::driver::IdArray<$id_type, $data_type, { $crate::count_paren_items!($($t)*) }> =
340-
$crate::driver::IdArray::new(
341-
$crate::first_item!($id_type, $($t)*), $crate::second_item!($($t)*));
390+
$crate::_new_id_array!((
391+
$crate::first_item!($id_type, $($t)*), $crate::second_item!($($t)*)), $id_type);
342392
};
343393
}
344394

rust/kernel/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#![feature(coerce_unsized)]
1717
#![feature(const_maybe_uninit_zeroed)]
1818
#![feature(const_refs_to_cell)]
19-
#![feature(const_trait_impl)]
2019
#![feature(dispatch_from_dyn)]
2120
#![feature(new_uninit)]
2221
#![feature(offset_of)]

0 commit comments

Comments
 (0)