@@ -187,12 +187,121 @@ pub struct KernelStaticParams<System> {
187
187
/// The members of this trait are implementation details and not meant to be
188
188
/// implemented externally. Use [`attach_static!`] or [`DelegateKernelStatic`]
189
189
/// 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" ) ]
190
244
pub trait KernelStatic < System = Self > {
191
245
const CFG_STARTUP_HOOKS : & ' static [ hook:: StartupHookAttr ] ;
192
246
const CFG_INTERRUPT_HANDLERS : & ' static [ Option < interrupt:: InterruptHandlerFn > ] ;
193
247
fn cfg_hunk_pool_ptr ( ) -> * mut u8 ;
194
248
}
195
249
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
196
305
pub trait DelegateKernelStatic < System > {
197
306
type Target : KernelStatic < System > ;
198
307
}
@@ -213,7 +322,9 @@ impl<T: DelegateKernelStatic<System>, System> KernelStatic<System> for T {
213
322
/// type `$System`.
214
323
///
215
324
/// 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.
217
328
pub macro attach_static ( $params: expr, impl KernelStatic <$System: ty> for $Ty: ty $( , ) ?) {
218
329
const _: ( ) = {
219
330
use $crate:: {
0 commit comments