Commit a1514b4
authored
Rollup merge of #65479 - SimonSapin:matches, r=alexcrichton
Add the `matches!( $expr, $pat ) -> bool` macro
# Motivation
This macro is:
* General-purpose (not domain-specific)
* Simple (the implementation is short)
* Very popular [on crates.io](https://crates.io/crates/matches) (currently 37th in all-time downloads)
* The two previous points combined make it number one in [left-pad index](https://twitter.com/bascule/status/1184523027888988160) score
As such, I feel it is a good candidate for inclusion in the standard library.
In fact I already felt that way five years ago: #14685 (Although the proof of popularity was not as strong at the time.)
# API
<details>
<del>
Back then, the main concern was that this macro may not be quite universally-enough useful to belong in the prelude.
Therefore, this PR adds the macro such that using it requires one of:
```rust
use core::macros::matches;
use std::macros::matches;
```
</del>
</details>
Like arms of a `match` expression, the macro supports multiple patterns separated by `|` and optionally followed by `if` and a guard expression:
```rust
let foo = 'f';
assert!(matches!(foo, 'A'..='Z' | 'a'..='z'));
let bar = Some(4);
assert!(matches!(bar, Some(x) if x > 2));
```
<details>
<del>
# Implementation constraints
A combination of reasons make it tricky for a standard library macro not to be in the prelude.
Currently, all public `macro_rules` macros in the standard library macros end up “in the prelude” of every crate not through `use std::prelude::v1::*;` like for other kinds of items, but through `#[macro_use]` on `extern crate std;`. (Both are injected by `src/libsyntax_ext/standard_library_imports.rs`.)
`#[macro_use]` seems to import every macro that is available at the top-level of a crate, even if through a `pub use` re-export.
Therefore, for `matches!` not to be in the prelude, we need it to be inside of a module rather than at the root of `core` or `std`.
However, the only way to make a `macro_rules` macro public outside of the crate where it is defined appears to be `#[macro_export]`. This exports the macro at the root of the crate regardless of which module defines it. See [macro scoping](https://doc.rust-lang.org/reference/macros-by-example.html#scoping-exporting-and-importing) in the reference.
Therefore, the macro needs to be defined in a crate that is not `core` or `std`.
# Implementation
This PR adds a new `matches_macro` crate as a private implementation detail of the standard library. This crate is `#![no_core]` so that libcore can depend on it. It contains a `macro_rules` definition with `#[macro_export]`.
libcore and libstd each have a new public `macros` module that contains a `pub use` re-export of the macro. Both the module and the macro are unstable, for now.
The existing private `macros` modules are renamed `prelude_macros`, though their respective source remains in `macros.rs` files.
</del>
</details>2 files changed
+29
-0
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
238 | 238 | | |
239 | 239 | | |
240 | 240 | | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
241 | 268 | | |
242 | 269 | | |
243 | 270 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
276 | 276 | | |
277 | 277 | | |
278 | 278 | | |
| 279 | + | |
279 | 280 | | |
280 | 281 | | |
281 | 282 | | |
| |||
527 | 528 | | |
528 | 529 | | |
529 | 530 | | |
| 531 | + | |
530 | 532 | | |
531 | 533 | | |
532 | 534 | | |
| |||
0 commit comments