Skip to content

Commit 3c4c2f2

Browse files
hoshinolinajannau
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 <lina@asahilina.net>
1 parent 32877ad commit 3c4c2f2

3 files changed

Lines changed: 82 additions & 43 deletions

File tree

rust/kernel/driver.rs

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ impl<T: DriverOps> Drop for Registration<T> {
126126
/// - [`RawDeviceId::ZERO`] is actually a zeroed-out version of the raw device id.
127127
/// - [`RawDeviceId::to_rawid`] stores `offset` in the context/data field of the raw device id so
128128
/// that buses can recover the pointer to the data.
129-
#[const_trait]
130129
pub unsafe trait RawDeviceId {
131130
/// The raw type that holds the device id.
132131
///
@@ -138,13 +137,6 @@ pub unsafe trait RawDeviceId {
138137
/// Id tables created from [`Self`] use [`Self::ZERO`] as the sentinel to indicate the end of
139138
/// the table.
140139
const ZERO: Self::RawType;
141-
142-
/// Converts an id into a raw id.
143-
///
144-
/// `offset` is the offset from the memory location where the raw device id is stored to the
145-
/// location where its associated context information is stored. Implementations must store
146-
/// this in the appropriate context/data field of the raw type.
147-
fn to_rawid(&self, offset: isize) -> Self::RawType;
148140
}
149141

150142
/// A zero-terminated device id array.
@@ -166,35 +158,7 @@ pub struct IdArray<T: RawDeviceId, U, const N: usize> {
166158
}
167159

168160
impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
169-
/// Creates a new instance of the array.
170-
///
171-
/// The contents are derived from the given identifiers and context information.
172-
pub const fn new(ids: [T; N], infos: [Option<U>; N]) -> Self
173-
where
174-
T: ~const RawDeviceId + Copy,
175-
T::RawType: Copy + Clone,
176-
{
177-
let mut array = Self {
178-
ids: IdArrayIds {
179-
ids: [T::ZERO; N],
180-
sentinel: T::ZERO,
181-
},
182-
id_infos: infos,
183-
};
184-
let mut i = 0usize;
185-
while i < N {
186-
// SAFETY: Both pointers are within `array` (or one byte beyond), consequently they are
187-
// derived from the same allocated object. We are using a `u8` pointer, whose size 1,
188-
// so the pointers are necessarily 1-byte aligned.
189-
let offset = unsafe {
190-
(&array.id_infos[i] as *const _ as *const u8)
191-
.offset_from(&array.ids.ids[i] as *const _ as _)
192-
};
193-
array.ids.ids[i] = ids[i].to_rawid(offset);
194-
i += 1;
195-
}
196-
array
197-
}
161+
const U_NONE: Option<U> = None;
198162

199163
/// Returns an `IdTable` backed by `self`.
200164
///
@@ -214,10 +178,82 @@ impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
214178
/// Returns the inner IdArrayIds array, without the context data.
215179
pub const fn as_ids(&self) -> IdArrayIds<T, N>
216180
where
217-
T: ~const RawDeviceId + Copy,
181+
T: RawDeviceId + Copy,
218182
{
219183
self.ids
220184
}
185+
186+
/// Creates a new instance of the array.
187+
///
188+
/// The contents are derived from the given identifiers and context information.
189+
#[doc(hidden)]
190+
pub const unsafe fn new(raw_ids: [T::RawType; N], infos: [Option<U>; N]) -> Self
191+
where
192+
T: RawDeviceId + Copy,
193+
T::RawType: Copy + Clone,
194+
{
195+
Self {
196+
ids: IdArrayIds {
197+
ids: raw_ids,
198+
sentinel: T::ZERO,
199+
},
200+
id_infos: infos,
201+
}
202+
}
203+
204+
#[doc(hidden)]
205+
pub const fn get_offset(idx: usize) -> isize
206+
where
207+
T: RawDeviceId + Copy,
208+
T::RawType: Copy + Clone,
209+
{
210+
// SAFETY: We are only using this dummy value to get offsets.
211+
let array = unsafe { Self::new([T::ZERO; N], [Self::U_NONE; N]) };
212+
// SAFETY: Both pointers are within `array` (or one byte beyond), consequently they are
213+
// derived from the same allocated object. We are using a `u8` pointer, whose size 1,
214+
// so the pointers are necessarily 1-byte aligned.
215+
let ret = unsafe {
216+
(&array.id_infos[idx] as *const _ as *const u8)
217+
.offset_from(&array.ids.ids[idx] as *const _ as _)
218+
};
219+
core::mem::forget(array);
220+
ret
221+
}
222+
}
223+
224+
// Creates a new ID array. This is a macro so it can take as a parameter the concrete ID type in order
225+
// to call to_rawid() on it, and still remain const. This is necessary until a new const_trait_impl
226+
// implementation lands, since the existing implementation was removed in Rust 1.73.
227+
#[macro_export]
228+
#[doc(hidden)]
229+
macro_rules! _new_id_array {
230+
(($($args:tt)*), $id_type:ty) => {{
231+
/// Creates a new instance of the array.
232+
///
233+
/// The contents are derived from the given identifiers and context information.
234+
const fn new< U, const N: usize>(ids: [$id_type; N], infos: [Option<U>; N])
235+
-> $crate::driver::IdArray<$id_type, U, N>
236+
where
237+
$id_type: $crate::driver::RawDeviceId + Copy,
238+
<$id_type as $crate::driver::RawDeviceId>::RawType: Copy + Clone,
239+
{
240+
let mut raw_ids =
241+
[<$id_type as $crate::driver::RawDeviceId>::ZERO; N];
242+
let mut i = 0usize;
243+
while i < N {
244+
let offset: isize = $crate::driver::IdArray::<$id_type, U, N>::get_offset(i);
245+
raw_ids[i] = ids[i].to_rawid(offset);
246+
i += 1;
247+
}
248+
249+
// SAFETY: We are passing valid arguments computed with the correct offsets.
250+
unsafe {
251+
$crate::driver::IdArray::<$id_type, U, N>::new(raw_ids, infos)
252+
}
253+
}
254+
255+
new($($args)*)
256+
}}
221257
}
222258

223259
/// A device id table.
@@ -375,8 +411,8 @@ macro_rules! define_id_array {
375411
($table_name:ident, $id_type:ty, $data_type:ty, [ $($t:tt)* ]) => {
376412
const $table_name:
377413
$crate::driver::IdArray<$id_type, $data_type, { $crate::count_paren_items!($($t)*) }> =
378-
$crate::driver::IdArray::new(
379-
$crate::first_item!($id_type, $($t)*), $crate::second_item!($($t)*));
414+
$crate::_new_id_array!((
415+
$crate::first_item!($id_type, $($t)*), $crate::second_item!($($t)*)), $id_type);
380416
};
381417
}
382418

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_mut_refs)]
1818
#![feature(const_refs_to_cell)]
19-
#![feature(const_trait_impl)]
2019
#![feature(dispatch_from_dyn)]
2120
#![feature(duration_constants)]
2221
#![feature(new_uninit)]

rust/kernel/of.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use core::num::NonZeroU32;
1515
use crate::{
1616
alloc::flags::*,
1717
bindings, driver,
18+
driver::RawDeviceId,
1819
prelude::*,
1920
str::{BStr, CStr},
2021
};
@@ -74,16 +75,19 @@ macro_rules! module_of_id_table {
7475
}
7576

7677
// SAFETY: `ZERO` is all zeroed-out and `to_rawid` stores `offset` in `of_device_id::data`.
77-
unsafe impl const driver::RawDeviceId for DeviceId {
78+
unsafe impl driver::RawDeviceId for DeviceId {
7879
type RawType = bindings::of_device_id;
7980
const ZERO: Self::RawType = bindings::of_device_id {
8081
name: [0; 32],
8182
type_: [0; 32],
8283
compatible: [0; 128],
8384
data: core::ptr::null(),
8485
};
86+
}
8587

86-
fn to_rawid(&self, offset: isize) -> Self::RawType {
88+
impl DeviceId {
89+
#[doc(hidden)]
90+
pub const fn to_rawid(&self, offset: isize) -> <Self as driver::RawDeviceId>::RawType {
8791
let DeviceId::Compatible(compatible) = self;
8892
let mut id = Self::ZERO;
8993
let mut i = 0;

0 commit comments

Comments
 (0)