Skip to content

Add the matches!( $expr, $pat ) -> bool macro#65479

Merged
bors merged 4 commits intorust-lang:masterfrom
SimonSapin:matches
Oct 24, 2019
Merged

Add the matches!( $expr, $pat ) -> bool macro#65479
bors merged 4 commits intorust-lang:masterfrom
SimonSapin:matches

Conversation

@SimonSapin
Copy link
Contributor

@SimonSapin SimonSapin commented Oct 16, 2019

Motivation

This macro is:

  • General-purpose (not domain-specific)
  • Simple (the implementation is short)
  • Very popular on crates.io (currently 37th in all-time downloads)
  • The two previous points combined make it number one in left-pad index 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

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:

use core::macros::matches;
use std::macros::matches;

Like arms of a match expression, the macro supports multiple patterns separated by | and optionally followed by if and a guard expression:

let foo = 'f';
assert!(matches!(foo, 'A'..='Z' | 'a'..='z'));

let bar = Some(4);
assert!(matches!(bar, Some(x) if x > 2));
Details

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 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.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.