@@ -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" ) ]
190244pub 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
196305pub 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.
217328pub macro attach_static ( $params: expr, impl KernelStatic <$System: ty> for $Ty: ty $( , ) ?) {
218329 const _: ( ) = {
219330 use $crate:: {
0 commit comments