1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
Remain sorted
=============
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/remain-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/remain)
[<img alt="crates.io" src="https://img.shields.io/crates/v/remain.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/remain)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-remain-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/remain)
[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/remain/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/remain/actions?query=branch%3Amaster)
This crate provides an attribute macro to check at compile time that the
variants of an enum or the arms of a match expression are written in sorted
order.
```toml
[dependencies]
remain = "0.2"
```
## Syntax
Place a `#[remain::sorted]` attribute on enums, structs, match-expressions, or
let-statements whose value is a match-expression.
Alternatively, import as `use remain::sorted;` and use `#[sorted]` as the
attribute.
```rust
#[remain::sorted]
#[derive(Debug)]
pub enum Error {
BlockSignal(signal::Error),
CreateCrasClient(libcras::Error),
CreateEventFd(sys_util::Error),
CreateSignalFd(sys_util::SignalFdError),
CreateSocket(io::Error),
DetectImageType(qcow::Error),
DeviceJail(io_jail::Error),
NetDeviceNew(virtio::NetError),
SpawnVcpu(io::Error),
}
#[remain::sorted]
#[derive(Debug)]
pub struct Registers {
ax: u16,
cx: u16,
di: u16,
si: u16,
sp: u16,
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
#[remain::sorted]
match self {
BlockSignal(e) => write!(f, "failed to block signal: {}", e),
CreateCrasClient(e) => write!(f, "failed to create cras client: {}", e),
CreateEventFd(e) => write!(f, "failed to create eventfd: {}", e),
CreateSignalFd(e) => write!(f, "failed to create signalfd: {}", e),
CreateSocket(e) => write!(f, "failed to create socket: {}", e),
DetectImageType(e) => write!(f, "failed to detect disk image type: {}", e),
DeviceJail(e) => write!(f, "failed to jail device: {}", e),
NetDeviceNew(e) => write!(f, "failed to set up virtio networking: {}", e),
SpawnVcpu(e) => write!(f, "failed to spawn VCPU thread: {}", e),
}
}
}
```
If an enum variant, struct field, or match arm is inserted out of order,
```diff
NetDeviceNew(virtio::NetError),
SpawnVcpu(io::Error),
+ AaaUhOh(Box<dyn StdError>),
}
```
then the macro produces a compile error.
```console
error: AaaUhOh should sort before BlockSignal
--> tests/stable.rs:49:5
|
49 | AaaUhOh(Box<dyn StdError>),
| ^^^^^^^
```
## Compiler support
The attribute on enums and structs is supported on any rustc version 1.31+.
Rust does not yet have stable support for user-defined attributes within a
function body, so the attribute on match-expressions and let-statements requires
a nightly compiler and the following two features enabled:
```rust
#![feature(proc_macro_hygiene, stmt_expr_attributes)]
```
As a stable alternative, this crate provides a function-level attribute called
`#[remain::check]` which makes match-expression and let-statement attributes
work on any rustc version 1.31+. Place this attribute on any function containing
`#[sorted]` to make them work on a stable compiler.
```rust
impl Display for Error {
#[remain::check]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
#[sorted]
match self {
/* ... */
}
}
}
```
<br>
#### License
<sup>
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
</sup>
<br>
<sub>
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.
</sub>
|