Skip to content

Commit 3ac16f2

Browse files
committed
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 3d2352c commit 3ac16f2

File tree

3 files changed

+82
-43
lines changed

3 files changed

+82
-43
lines changed

rust/kernel/driver.rs

Lines changed: 76 additions & 40 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.
@@ -159,35 +151,7 @@ pub struct IdArray<T: RawDeviceId, U, const N: usize> {
159151
}
160152

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

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

216252
/// A device id table.
@@ -368,8 +404,8 @@ macro_rules! define_id_array {
368404
($table_name:ident, $id_type:ty, $data_type:ty, [ $($t:tt)* ]) => {
369405
const $table_name:
370406
$crate::driver::IdArray<$id_type, $data_type, { $crate::count_paren_items!($($t)*) }> =
371-
$crate::driver::IdArray::new(
372-
$crate::first_item!($id_type, $($t)*), $crate::second_item!($($t)*));
407+
$crate::_new_id_array!((
408+
$crate::first_item!($id_type, $($t)*), $crate::second_item!($($t)*)), $id_type);
373409
};
374410
}
375411

rust/kernel/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#![feature(const_maybe_uninit_zeroed)]
1919
#![feature(const_mut_refs)]
2020
#![feature(const_refs_to_cell)]
21-
#![feature(const_trait_impl)]
2221
#![feature(dispatch_from_dyn)]
2322
#![feature(duration_constants)]
2423
#![feature(new_uninit)]

rust/kernel/of.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use core::num::NonZeroU32;
1414

1515
use crate::{
1616
bindings, driver,
17+
driver::RawDeviceId,
1718
prelude::*,
1819
str::{BStr, CStr},
1920
};
@@ -73,16 +74,19 @@ macro_rules! module_of_id_table {
7374
}
7475

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

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

0 commit comments

Comments
 (0)