| 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | |
| 3 | //! Crate for all kernel procedural macros. |
| 4 | |
| 5 | // When fixdep scans this, it will find this string `CONFIG_RUSTC_VERSION_TEXT` |
| 6 | // and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is |
| 7 | // touched by Kconfig when the version string from the compiler changes. |
| 8 | |
| 9 | // Stable since Rust 1.87.0. |
| 10 | |
| 11 | // |
| 12 | // Stable since Rust 1.88.0 under a different name, `proc_macro_span_file`, |
| 13 | // which was added in Rust 1.88.0. This is why `cfg_attr` is used here, i.e. |
| 14 | // to avoid depending on the full `proc_macro_span` on Rust >= 1.88.0. |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 | use TokenStream; |
| 28 | |
| 29 | use parse_macro_input; |
| 30 | |
| 31 | /// Declares a kernel module. |
| 32 | /// |
| 33 | /// The `type` argument should be a type which implements the [`Module`] |
| 34 | /// trait. Also accepts various forms of kernel metadata. |
| 35 | /// |
| 36 | /// The `params` field describe module parameters. Each entry has the form |
| 37 | /// |
| 38 | /// ```ignore |
| 39 | /// parameter_name: type { |
| 40 | /// default: default_value, |
| 41 | /// description: "Description", |
| 42 | /// } |
| 43 | /// ``` |
| 44 | /// |
| 45 | /// `type` may be one of |
| 46 | /// |
| 47 | /// - [`i8`] |
| 48 | /// - [`u8`] |
| 49 | /// - [`i8`] |
| 50 | /// - [`u8`] |
| 51 | /// - [`i16`] |
| 52 | /// - [`u16`] |
| 53 | /// - [`i32`] |
| 54 | /// - [`u32`] |
| 55 | /// - [`i64`] |
| 56 | /// - [`u64`] |
| 57 | /// - [`isize`] |
| 58 | /// - [`usize`] |
| 59 | /// - [`bool`] |
| 60 | /// |
| 61 | /// C header: [`include/linux/moduleparam.h`](srctree/include/linux/moduleparam.h) |
| 62 | /// |
| 63 | /// [`Module`]: ../kernel/trait.Module.html |
| 64 | /// |
| 65 | /// # Examples |
| 66 | /// |
| 67 | /// ```ignore |
| 68 | /// use kernel::prelude::*; |
| 69 | /// |
| 70 | /// module!{ |
| 71 | /// type: MyModule, |
| 72 | /// name: "my_kernel_module", |
| 73 | /// authors: ["Rust for Linux Contributors"], |
| 74 | /// description: "My very own kernel module!", |
| 75 | /// license: "GPL", |
| 76 | /// alias: ["alternate_module_name"], |
| 77 | /// params: { |
| 78 | /// my_parameter: i64 { |
| 79 | /// default: 1, |
| 80 | /// description: "This parameter has a default of 1", |
| 81 | /// }, |
| 82 | /// }, |
| 83 | /// } |
| 84 | /// |
| 85 | /// struct MyModule(i32); |
| 86 | /// |
| 87 | /// impl kernel::Module for MyModule { |
| 88 | /// fn init(_module: &'static ThisModule) -> Result<Self> { |
| 89 | /// let foo: i32 = 42; |
| 90 | /// pr_info!("I contain: {}\n", foo); |
| 91 | /// pr_info!("i32 param is: {}\n", module_parameters::my_parameter.read()); |
| 92 | /// Ok(Self(foo)) |
| 93 | /// } |
| 94 | /// } |
| 95 | /// # fn main() {} |
| 96 | /// ``` |
| 97 | /// |
| 98 | /// ## Firmware |
| 99 | /// |
| 100 | /// The following example shows how to declare a kernel module that needs |
| 101 | /// to load binary firmware files. You need to specify the file names of |
| 102 | /// the firmware in the `firmware` field. The information is embedded |
| 103 | /// in the `modinfo` section of the kernel module. For example, a tool to |
| 104 | /// build an initramfs uses this information to put the firmware files into |
| 105 | /// the initramfs image. |
| 106 | /// |
| 107 | /// ``` |
| 108 | /// use kernel::prelude::*; |
| 109 | /// |
| 110 | /// module!{ |
| 111 | /// type: MyDeviceDriverModule, |
| 112 | /// name: "my_device_driver_module", |
| 113 | /// authors: ["Rust for Linux Contributors"], |
| 114 | /// description: "My device driver requires firmware", |
| 115 | /// license: "GPL", |
| 116 | /// firmware: ["my_device_firmware1.bin", "my_device_firmware2.bin"], |
| 117 | /// } |
| 118 | /// |
| 119 | /// struct MyDeviceDriverModule; |
| 120 | /// |
| 121 | /// impl kernel::Module for MyDeviceDriverModule { |
| 122 | /// fn init(_module: &'static ThisModule) -> Result<Self> { |
| 123 | /// Ok(Self) |
| 124 | /// } |
| 125 | /// } |
| 126 | /// # fn main() {} |
| 127 | /// ``` |
| 128 | /// |
| 129 | /// # Supported argument types |
| 130 | /// - `type`: type which implements the [`Module`] trait (required). |
| 131 | /// - `name`: ASCII string literal of the name of the kernel module (required). |
| 132 | /// - `authors`: array of ASCII string literals of the authors of the kernel module. |
| 133 | /// - `description`: string literal of the description of the kernel module. |
| 134 | /// - `license`: ASCII string literal of the license of the kernel module (required). |
| 135 | /// - `alias`: array of ASCII string literals of the alias names of the kernel module. |
| 136 | /// - `firmware`: array of ASCII string literals of the firmware files of |
| 137 | /// the kernel module. |
| 138 | |
| 139 | |
| 140 | module |
| 141 | .unwrap_or_else |
| 142 | .into |
| 143 | |
| 144 | |
| 145 | /// Declares or implements a vtable trait. |
| 146 | /// |
| 147 | /// Linux's use of pure vtables is very close to Rust traits, but they differ |
| 148 | /// in how unimplemented functions are represented. In Rust, traits can provide |
| 149 | /// default implementation for all non-required methods (and the default |
| 150 | /// implementation could just return `Error::EINVAL`); Linux typically use C |
| 151 | /// `NULL` pointers to represent these functions. |
| 152 | /// |
| 153 | /// This attribute closes that gap. A trait can be annotated with the |
| 154 | /// `#[vtable]` attribute. Implementers of the trait will then also have to |
| 155 | /// annotate the trait with `#[vtable]`. This attribute generates a `HAS_*` |
| 156 | /// associated constant bool for each method in the trait that is set to true if |
| 157 | /// the implementer has overridden the associated method. |
| 158 | /// |
| 159 | /// For a trait method to be optional, it must have a default implementation. |
| 160 | /// This is also the case for traits annotated with `#[vtable]`, but in this |
| 161 | /// case the default implementation will never be executed. The reason for this |
| 162 | /// is that the functions will be called through function pointers installed in |
| 163 | /// C side vtables. When an optional method is not implemented on a `#[vtable]` |
| 164 | /// trait, a `NULL` entry is installed in the vtable. Thus the default |
| 165 | /// implementation is never called. Since these traits are not designed to be |
| 166 | /// used on the Rust side, it should not be possible to call the default |
| 167 | /// implementation. This is done to ensure that we call the vtable methods |
| 168 | /// through the C vtable, and not through the Rust vtable. Therefore, the |
| 169 | /// default implementation should call `build_error!`, which prevents |
| 170 | /// calls to this function at compile time: |
| 171 | /// |
| 172 | /// ```compile_fail |
| 173 | /// # // Intentionally missing `use`s to simplify `rusttest`. |
| 174 | /// build_error!(VTABLE_DEFAULT_ERROR) |
| 175 | /// ``` |
| 176 | /// |
| 177 | /// Note that you might need to import [`kernel::error::VTABLE_DEFAULT_ERROR`]. |
| 178 | /// |
| 179 | /// This macro should not be used when all functions are required. |
| 180 | /// |
| 181 | /// Additionally, this macro automatically handles the `OwnerModule` |
| 182 | /// associated type: on the trait side, `type OwnerModule: ModuleMetadata;` |
| 183 | /// is added as a required associated type if not already defined; on the |
| 184 | /// impl side, `type OwnerModule = LocalModule;` is automatically inserted |
| 185 | /// if not explicitly defined. |
| 186 | /// |
| 187 | /// # Examples |
| 188 | /// |
| 189 | /// ``` |
| 190 | /// use kernel::error::VTABLE_DEFAULT_ERROR; |
| 191 | /// use kernel::prelude::*; |
| 192 | /// |
| 193 | /// # struct LocalModule; |
| 194 | /// # impl kernel::ModuleMetadata for LocalModule { |
| 195 | /// # const NAME: &'static kernel::str::CStr = c"vtable_doctest"; |
| 196 | /// # |
| 197 | /// # // SAFETY: This doctest runs on the host: there is no `THIS_MODULE`. |
| 198 | /// # const THIS_MODULE: kernel::ThisModule = unsafe { |
| 199 | /// # kernel::ThisModule::from_ptr(core::ptr::null_mut()) |
| 200 | /// # }; |
| 201 | /// # } |
| 202 | /// # |
| 203 | /// # fn main() { |
| 204 | /// // Declares a `#[vtable]` trait |
| 205 | /// #[vtable] |
| 206 | /// pub trait Operations: Send + Sync + Sized { |
| 207 | /// fn foo(&self) -> Result<()> { |
| 208 | /// build_error!(VTABLE_DEFAULT_ERROR) |
| 209 | /// } |
| 210 | /// |
| 211 | /// fn bar(&self) -> Result<()> { |
| 212 | /// build_error!(VTABLE_DEFAULT_ERROR) |
| 213 | /// } |
| 214 | /// } |
| 215 | /// |
| 216 | /// struct Foo; |
| 217 | /// |
| 218 | /// // Implements the `#[vtable]` trait |
| 219 | /// #[vtable] |
| 220 | /// impl Operations for Foo { |
| 221 | /// fn foo(&self) -> Result<()> { |
| 222 | /// # Err(EINVAL) |
| 223 | /// // ... |
| 224 | /// } |
| 225 | /// } |
| 226 | /// |
| 227 | /// assert_eq!(<Foo as Operations>::HAS_FOO, true); |
| 228 | /// assert_eq!(<Foo as Operations>::HAS_BAR, false); |
| 229 | /// # } |
| 230 | /// ``` |
| 231 | /// |
| 232 | /// [`kernel::error::VTABLE_DEFAULT_ERROR`]: ../kernel/error/constant.VTABLE_DEFAULT_ERROR.html |
| 233 | |
| 234 | |
| 235 | parse_macro_input!; |
| 236 | vtable |
| 237 | .unwrap_or_else |
| 238 | .into |
| 239 | |
| 240 | |
| 241 | /// Export a function so that C code can call it via a header file. |
| 242 | /// |
| 243 | /// Functions exported using this macro can be called from C code using the declaration in the |
| 244 | /// appropriate header file. It should only be used in cases where C calls the function through a |
| 245 | /// header file; cases where C calls into Rust via a function pointer in a vtable (such as |
| 246 | /// `file_operations`) should not use this macro. |
| 247 | /// |
| 248 | /// This macro has the following effect: |
| 249 | /// |
| 250 | /// * Disables name mangling for this function. |
| 251 | /// * Verifies at compile-time that the function signature matches the declaration in the header |
| 252 | /// file. |
| 253 | /// |
| 254 | /// You must declare the signature of the Rust function in a header file that is included by |
| 255 | /// `rust/bindings/bindings_helper.h`. |
| 256 | /// |
| 257 | /// This macro is *not* the same as the C macros `EXPORT_SYMBOL_*`. All Rust symbols are currently |
| 258 | /// automatically exported with `EXPORT_SYMBOL_GPL`. |
| 259 | |
| 260 | |
| 261 | parse_macro_input!; |
| 262 | export.into |
| 263 | |
| 264 | |
| 265 | /// Like [`core::format_args!`], but automatically wraps arguments in [`kernel::fmt::Adapter`]. |
| 266 | /// |
| 267 | /// This macro allows generating `fmt::Arguments` while ensuring that each argument is wrapped with |
| 268 | /// `::kernel::fmt::Adapter`, which customizes formatting behavior for kernel logging. |
| 269 | /// |
| 270 | /// Named arguments used in the format string (e.g. `{foo}`) are detected and resolved from local |
| 271 | /// bindings. All positional and named arguments are automatically wrapped. |
| 272 | /// |
| 273 | /// This macro is an implementation detail of other kernel logging macros like [`pr_info!`] and |
| 274 | /// should not typically be used directly. |
| 275 | /// |
| 276 | /// [`kernel::fmt::Adapter`]: ../kernel/fmt/struct.Adapter.html |
| 277 | /// [`pr_info!`]: ../kernel/macro.pr_info.html |
| 278 | |
| 279 | |
| 280 | fmt.into |
| 281 | |
| 282 | |
| 283 | /// Concatenate two identifiers. |
| 284 | /// |
| 285 | /// This is useful in macros that need to declare or reference items with names |
| 286 | /// starting with a fixed prefix and ending in a user specified name. The resulting |
| 287 | /// identifier has the span of the second argument. |
| 288 | /// |
| 289 | /// # Examples |
| 290 | /// |
| 291 | /// ``` |
| 292 | /// # const binder_driver_return_protocol_BR_OK: u32 = 0; |
| 293 | /// # const binder_driver_return_protocol_BR_ERROR: u32 = 1; |
| 294 | /// # const binder_driver_return_protocol_BR_TRANSACTION: u32 = 2; |
| 295 | /// # const binder_driver_return_protocol_BR_REPLY: u32 = 3; |
| 296 | /// # const binder_driver_return_protocol_BR_DEAD_REPLY: u32 = 4; |
| 297 | /// # const binder_driver_return_protocol_BR_TRANSACTION_COMPLETE: u32 = 5; |
| 298 | /// # const binder_driver_return_protocol_BR_INCREFS: u32 = 6; |
| 299 | /// # const binder_driver_return_protocol_BR_ACQUIRE: u32 = 7; |
| 300 | /// # const binder_driver_return_protocol_BR_RELEASE: u32 = 8; |
| 301 | /// # const binder_driver_return_protocol_BR_DECREFS: u32 = 9; |
| 302 | /// # const binder_driver_return_protocol_BR_NOOP: u32 = 10; |
| 303 | /// # const binder_driver_return_protocol_BR_SPAWN_LOOPER: u32 = 11; |
| 304 | /// # const binder_driver_return_protocol_BR_DEAD_BINDER: u32 = 12; |
| 305 | /// # const binder_driver_return_protocol_BR_CLEAR_DEATH_NOTIFICATION_DONE: u32 = 13; |
| 306 | /// # const binder_driver_return_protocol_BR_FAILED_REPLY: u32 = 14; |
| 307 | /// use kernel::macros::concat_idents; |
| 308 | /// |
| 309 | /// macro_rules! pub_no_prefix { |
| 310 | /// ($prefix:ident, $($newname:ident),+) => { |
| 311 | /// $(pub(crate) const $newname: u32 = concat_idents!($prefix, $newname);)+ |
| 312 | /// }; |
| 313 | /// } |
| 314 | /// |
| 315 | /// pub_no_prefix!( |
| 316 | /// binder_driver_return_protocol_, |
| 317 | /// BR_OK, |
| 318 | /// BR_ERROR, |
| 319 | /// BR_TRANSACTION, |
| 320 | /// BR_REPLY, |
| 321 | /// BR_DEAD_REPLY, |
| 322 | /// BR_TRANSACTION_COMPLETE, |
| 323 | /// BR_INCREFS, |
| 324 | /// BR_ACQUIRE, |
| 325 | /// BR_RELEASE, |
| 326 | /// BR_DECREFS, |
| 327 | /// BR_NOOP, |
| 328 | /// BR_SPAWN_LOOPER, |
| 329 | /// BR_DEAD_BINDER, |
| 330 | /// BR_CLEAR_DEATH_NOTIFICATION_DONE, |
| 331 | /// BR_FAILED_REPLY |
| 332 | /// ); |
| 333 | /// |
| 334 | /// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK); |
| 335 | /// ``` |
| 336 | |
| 337 | |
| 338 | concat_idents.into |
| 339 | |
| 340 | |
| 341 | /// Paste identifiers together. |
| 342 | /// |
| 343 | /// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a |
| 344 | /// single identifier. |
| 345 | /// |
| 346 | /// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers and |
| 347 | /// literals (lifetimes and documentation strings are not supported). There is a difference in |
| 348 | /// supported modifiers as well. |
| 349 | /// |
| 350 | /// # Examples |
| 351 | /// |
| 352 | /// ``` |
| 353 | /// # const binder_driver_return_protocol_BR_OK: u32 = 0; |
| 354 | /// # const binder_driver_return_protocol_BR_ERROR: u32 = 1; |
| 355 | /// # const binder_driver_return_protocol_BR_TRANSACTION: u32 = 2; |
| 356 | /// # const binder_driver_return_protocol_BR_REPLY: u32 = 3; |
| 357 | /// # const binder_driver_return_protocol_BR_DEAD_REPLY: u32 = 4; |
| 358 | /// # const binder_driver_return_protocol_BR_TRANSACTION_COMPLETE: u32 = 5; |
| 359 | /// # const binder_driver_return_protocol_BR_INCREFS: u32 = 6; |
| 360 | /// # const binder_driver_return_protocol_BR_ACQUIRE: u32 = 7; |
| 361 | /// # const binder_driver_return_protocol_BR_RELEASE: u32 = 8; |
| 362 | /// # const binder_driver_return_protocol_BR_DECREFS: u32 = 9; |
| 363 | /// # const binder_driver_return_protocol_BR_NOOP: u32 = 10; |
| 364 | /// # const binder_driver_return_protocol_BR_SPAWN_LOOPER: u32 = 11; |
| 365 | /// # const binder_driver_return_protocol_BR_DEAD_BINDER: u32 = 12; |
| 366 | /// # const binder_driver_return_protocol_BR_CLEAR_DEATH_NOTIFICATION_DONE: u32 = 13; |
| 367 | /// # const binder_driver_return_protocol_BR_FAILED_REPLY: u32 = 14; |
| 368 | /// macro_rules! pub_no_prefix { |
| 369 | /// ($prefix:ident, $($newname:ident),+) => { |
| 370 | /// ::kernel::macros::paste! { |
| 371 | /// $(pub(crate) const $newname: u32 = [<$prefix $newname>];)+ |
| 372 | /// } |
| 373 | /// }; |
| 374 | /// } |
| 375 | /// |
| 376 | /// pub_no_prefix!( |
| 377 | /// binder_driver_return_protocol_, |
| 378 | /// BR_OK, |
| 379 | /// BR_ERROR, |
| 380 | /// BR_TRANSACTION, |
| 381 | /// BR_REPLY, |
| 382 | /// BR_DEAD_REPLY, |
| 383 | /// BR_TRANSACTION_COMPLETE, |
| 384 | /// BR_INCREFS, |
| 385 | /// BR_ACQUIRE, |
| 386 | /// BR_RELEASE, |
| 387 | /// BR_DECREFS, |
| 388 | /// BR_NOOP, |
| 389 | /// BR_SPAWN_LOOPER, |
| 390 | /// BR_DEAD_BINDER, |
| 391 | /// BR_CLEAR_DEATH_NOTIFICATION_DONE, |
| 392 | /// BR_FAILED_REPLY |
| 393 | /// ); |
| 394 | /// |
| 395 | /// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK); |
| 396 | /// ``` |
| 397 | /// |
| 398 | /// # Modifiers |
| 399 | /// |
| 400 | /// For each identifier, it is possible to attach one or multiple modifiers to |
| 401 | /// it. |
| 402 | /// |
| 403 | /// Currently supported modifiers are: |
| 404 | /// * `span`: change the span of concatenated identifier to the span of the specified token. By |
| 405 | /// default the span of the `[< >]` group is used. |
| 406 | /// * `lower`: change the identifier to lower case. |
| 407 | /// * `upper`: change the identifier to upper case. |
| 408 | /// |
| 409 | /// ``` |
| 410 | /// # const binder_driver_return_protocol_BR_OK: u32 = 0; |
| 411 | /// # const binder_driver_return_protocol_BR_ERROR: u32 = 1; |
| 412 | /// # const binder_driver_return_protocol_BR_TRANSACTION: u32 = 2; |
| 413 | /// # const binder_driver_return_protocol_BR_REPLY: u32 = 3; |
| 414 | /// # const binder_driver_return_protocol_BR_DEAD_REPLY: u32 = 4; |
| 415 | /// # const binder_driver_return_protocol_BR_TRANSACTION_COMPLETE: u32 = 5; |
| 416 | /// # const binder_driver_return_protocol_BR_INCREFS: u32 = 6; |
| 417 | /// # const binder_driver_return_protocol_BR_ACQUIRE: u32 = 7; |
| 418 | /// # const binder_driver_return_protocol_BR_RELEASE: u32 = 8; |
| 419 | /// # const binder_driver_return_protocol_BR_DECREFS: u32 = 9; |
| 420 | /// # const binder_driver_return_protocol_BR_NOOP: u32 = 10; |
| 421 | /// # const binder_driver_return_protocol_BR_SPAWN_LOOPER: u32 = 11; |
| 422 | /// # const binder_driver_return_protocol_BR_DEAD_BINDER: u32 = 12; |
| 423 | /// # const binder_driver_return_protocol_BR_CLEAR_DEATH_NOTIFICATION_DONE: u32 = 13; |
| 424 | /// # const binder_driver_return_protocol_BR_FAILED_REPLY: u32 = 14; |
| 425 | /// macro_rules! pub_no_prefix { |
| 426 | /// ($prefix:ident, $($newname:ident),+) => { |
| 427 | /// ::kernel::macros::paste! { |
| 428 | /// $(pub(crate) const fn [<$newname:lower:span>]() -> u32 { [<$prefix $newname:span>] })+ |
| 429 | /// } |
| 430 | /// }; |
| 431 | /// } |
| 432 | /// |
| 433 | /// pub_no_prefix!( |
| 434 | /// binder_driver_return_protocol_, |
| 435 | /// BR_OK, |
| 436 | /// BR_ERROR, |
| 437 | /// BR_TRANSACTION, |
| 438 | /// BR_REPLY, |
| 439 | /// BR_DEAD_REPLY, |
| 440 | /// BR_TRANSACTION_COMPLETE, |
| 441 | /// BR_INCREFS, |
| 442 | /// BR_ACQUIRE, |
| 443 | /// BR_RELEASE, |
| 444 | /// BR_DECREFS, |
| 445 | /// BR_NOOP, |
| 446 | /// BR_SPAWN_LOOPER, |
| 447 | /// BR_DEAD_BINDER, |
| 448 | /// BR_CLEAR_DEATH_NOTIFICATION_DONE, |
| 449 | /// BR_FAILED_REPLY |
| 450 | /// ); |
| 451 | /// |
| 452 | /// assert_eq!(br_ok(), binder_driver_return_protocol_BR_OK); |
| 453 | /// ``` |
| 454 | /// |
| 455 | /// # Literals |
| 456 | /// |
| 457 | /// Literals can also be concatenated with other identifiers: |
| 458 | /// |
| 459 | /// ``` |
| 460 | /// macro_rules! create_numbered_fn { |
| 461 | /// ($name:literal, $val:literal) => { |
| 462 | /// ::kernel::macros::paste! { |
| 463 | /// fn [<some_ $name _fn $val>]() -> u32 { $val } |
| 464 | /// } |
| 465 | /// }; |
| 466 | /// } |
| 467 | /// |
| 468 | /// create_numbered_fn!("foo", 100); |
| 469 | /// |
| 470 | /// assert_eq!(some_foo_fn100(), 100) |
| 471 | /// ``` |
| 472 | /// |
| 473 | /// [`paste`]: https://docs.rs/paste/ |
| 474 | |
| 475 | |
| 476 | let mut tokens = from.into_iter.collect; |
| 477 | expand; |
| 478 | tokens |
| 479 | .into_iter |
| 480 | . |
| 481 | .into |
| 482 | |
| 483 | |
| 484 | /// Registers a KUnit test suite and its test cases using a user-space like syntax. |
| 485 | /// |
| 486 | /// This macro should be used on modules. If `CONFIG_KUNIT` (in `.config`) is `n`, the target module |
| 487 | /// is ignored. |
| 488 | /// |
| 489 | /// # Examples |
| 490 | /// |
| 491 | /// ```ignore |
| 492 | /// # use kernel::prelude::*; |
| 493 | /// #[kunit_tests(kunit_test_suit_name)] |
| 494 | /// mod tests { |
| 495 | /// #[test] |
| 496 | /// fn foo() { |
| 497 | /// assert_eq!(1, 1); |
| 498 | /// } |
| 499 | /// |
| 500 | /// #[test] |
| 501 | /// fn bar() { |
| 502 | /// assert_eq!(2, 2); |
| 503 | /// } |
| 504 | /// } |
| 505 | /// ``` |
| 506 | |
| 507 | |
| 508 | kunit_tests |
| 509 | .unwrap_or_else |
| 510 | .into |
| 511 | |
| 512 | |
| 513 | /// Obtain a type that implements [`ForLt`] for the given higher-ranked type. |
| 514 | /// |
| 515 | /// Please refer to the documentation of the [`ForLt`] trait. |
| 516 | /// |
| 517 | /// [`ForLt`]: trait.ForLt.html |
| 518 | |
| 519 | |
| 520 | |
| 521 | for_lt.into |
| 522 | |
| 523 | |
| 524 | /// Obtain a type that implements [`CovariantForLt`] (and [`ForLt`]) for the given higher-ranked |
| 525 | /// type. |
| 526 | /// |
| 527 | /// Unlike [`ForLt!`], this macro additionally proves that the type is covariant over the lifetime, |
| 528 | /// providing a safe [`CovariantForLt::cast_ref`] method. |
| 529 | /// |
| 530 | /// Please refer to the documentation of the [`CovariantForLt`] trait. |
| 531 | /// |
| 532 | /// [`CovariantForLt`]: trait.CovariantForLt.html |
| 533 | /// [`CovariantForLt::cast_ref`]: trait.CovariantForLt.html#method.cast_ref |
| 534 | /// [`ForLt`]: trait.ForLt.html |
| 535 | |
| 536 | |
| 537 | |
| 538 | covariant_for_lt.into |
| 539 |