Skip to content

Commit 373887d

Browse files
committed
doc(kernel): improve the documentation around KernelStatic
1 parent 08b9fd4 commit 373887d

File tree

1 file changed

+112
-1
lines changed

1 file changed

+112
-1
lines changed

src/r3/src/kernel/cfg.rs

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,121 @@ pub struct KernelStaticParams<System> {
187187
/// The members of this trait are implementation details and not meant to be
188188
/// implemented externally. Use [`attach_static!`] or [`DelegateKernelStatic`]
189189
/// to implement this trait.
190+
///
191+
/// # Derivation and Usage
192+
///
193+
/// An implementation of this trait is derived from [`Cfg::finish_pre`][]'s
194+
/// output and consumed by [`Cfg::finish_post`][] through a type parameter. The
195+
/// following diagram shows the intended data flow.
196+
///
197+
/// <center>
198+
///
199+
#[doc = svgbobdoc::transform_mdstr!(
200+
/// ```svgbob
201+
/// .--------.
202+
/// | Cfg<C> |
203+
/// '--------'
204+
/// |
205+
/// v
206+
/// "Cfg::finish_pre"
207+
/// |
208+
/// .----------+----------.
209+
/// | |
210+
/// v v
211+
/// .--------. .-----------------------.
212+
/// | Cfg<C> | | KernelStaticParams<C> |
213+
/// '--------' '-----------------------'
214+
/// | |
215+
/// | v
216+
/// | "attach_static!"
217+
/// | |
218+
/// | v
219+
/// | .-------------------.
220+
/// | | impl KernelStatic |
221+
/// | | for C::System |
222+
/// | '-------------------'
223+
/// v |
224+
/// "Cfg::finish_interrupt"<--------+
225+
/// "(optional)" |
226+
/// | |
227+
/// v |
228+
/// "Cfg::finish_post"<----------+
229+
/// | |
230+
/// v v
231+
/// .---. Hunk API, etc.
232+
/// | C |
233+
/// '---'
234+
/// |
235+
/// v
236+
/// Kernel-specific
237+
/// configuration process
238+
/// ```
239+
)]
240+
///
241+
/// </center>
242+
///
243+
#[doc = include_str!("../common.md")]
190244
pub trait KernelStatic<System = Self> {
191245
const CFG_STARTUP_HOOKS: &'static [hook::StartupHookAttr];
192246
const CFG_INTERRUPT_HANDLERS: &'static [Option<interrupt::InterruptHandlerFn>];
193247
fn cfg_hunk_pool_ptr() -> *mut u8;
194248
}
195249

250+
/// The marker trait to generate a forwarding implementation of
251+
/// [`KernelStatic`][]`<System>`.
252+
///
253+
/// This is useful for circumventing [the orphan rules][1]. Suppose we have a
254+
/// kernel crate `r3_kernel` and an application crate `app`, and `r3_kernel`
255+
/// provides a system type `System<Traits>`, where `Traits` is a marker type to
256+
/// be defined in an application crate. For many reasons, `static` items to
257+
/// store a kernel state can only be defined in `app`, where the concrete form
258+
/// of the kernel is known. This means `impl KernelStatic for System<Traits>`
259+
/// has to appear in `app`, but since both `KernelStatic` and `System` are
260+
/// foreign to `app`, this is not allowed by the orphan rules.
261+
///
262+
/// ```rust,ignore
263+
/// // r3::kernel::cfg
264+
/// // ========================
265+
/// trait KernelStatic<System> {}
266+
///
267+
/// // r3_kernel
268+
/// // ========================
269+
/// struct System<Traits> { /* ... */ }
270+
///
271+
/// // app
272+
/// // ========================
273+
/// struct Traits;
274+
/// impl r3::kernel::cfg::KernelStatic<r3_kernel::System<Traits>>
275+
/// for r3_kernel::System<Traits> {} // E0117
276+
/// ```
277+
///
278+
/// The above example can be fixed by implementing `KernelStatic` on `Traits`
279+
/// instead and `DelegateKernelStatic` on `System`.
280+
///
281+
/// ```rust,ignore
282+
/// // r3::kernel::cfg
283+
/// // ========================
284+
/// trait KernelStatic<System> {}
285+
/// trait DelegateKernelStatic<System> { type Target; }
286+
/// impl<T, System> KernelStatic<System> for T
287+
/// where T: DelegateKernelStatic<System> {}
288+
///
289+
/// // r3_kernel
290+
/// // ========================
291+
/// struct System<Traits> { /* ... */ }
292+
/// impl<Traits> DelegateKernelStatic for System<Traits> {
293+
/// // Inherit `Traits`'s implementation
294+
/// type Target = Traits;
295+
/// }
296+
///
297+
/// // app
298+
/// // ========================
299+
/// struct Traits;
300+
/// impl r3::kernel::cfg::KernelStatic<r3_kernel::System<Traits>>
301+
/// for Traits {} // OK
302+
/// ```
303+
///
304+
/// [1]: https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html#concrete-orphan-rules
196305
pub trait DelegateKernelStatic<System> {
197306
type Target: KernelStatic<System>;
198307
}
@@ -213,7 +322,9 @@ impl<T: DelegateKernelStatic<System>, System> KernelStatic<System> for T {
213322
/// type `$System`.
214323
///
215324
/// This macro produces `static` items and a `KernelStatic<$System>`
216-
/// implementation for `$Ty`. It doesn't support generics.
325+
/// implementation for `$Ty`. It doesn't support generics, which means this
326+
/// macro should be invoked in an application crate, where the concrete system
327+
/// type is known.
217328
pub macro attach_static($params:expr, impl KernelStatic<$System:ty> for $Ty:ty $(,)?) {
218329
const _: () = {
219330
use $crate::{

0 commit comments

Comments
 (0)