This crate exports a macro which implements most of RFC 1303 (a "let-else" or "guard" expression as you can find in Swift).
The syntax proposed in the RFC was if !let PAT = EXPR { BODY }
or let PAT = EXPR else { BODY }
(where BODY
must diverge). This macro understands the latter syntax, as well as a variation proposed in the RFC with the else
clause in the middle.
```rust
use std::env;
fn main() { // read configuration from a certain environment variable // do nothing if the variable is missing guard!(let Ok(foo) = env::var("FOO") else { return });
println!("FOO = {}", foo);
} ```
nightly
enables nightly tests and uses expression attributes in the expansion (see RFC 16).
Requires #![feature(stmt_expr_attributes)]
in the client crate.
debug
enables trace_macros
for debugging. Requires a nightly compiler (but not this crate's nightly
feature).It's difficult to implement this behavior as a macro, because a let
statement must be created in the enclosing scope. Besides that, it is desirable to avoid the necessity of repeating the identifiers bound by the pattern. The strategy used here is to scan the pattern for identifiers, and use that to construct a top-level let
statement which internally uses a match
to apply the pattern. This scanning is almost possible -- see limitations #1 and #2 below.
This strategy also means that PAT
needs to be input to the macro as an unparsed sequence of token trees. There are two ways to take an unbounded sequence of token trees as input without causing ambiguity errors: put the token trees at the end (my current choice) or enclose them in brackets. Originally, this choice resulted in a backwards invocation syntax. Since version 0.2.0, more convenient syntaxes are supported by adopting a two-pass parsing strategy: the macro essentially takes its entire input as a sequence of tokens, splits on =
and else
, then parses the results again.
There are a number of subtleties in the expansion to avoid various warning and pitfalls; see the macro source for more details.
match
) instead.Empty(..)
until #29383 lands, after that include the enum name as in Enum::Empty
. (During the 1.6 beta you will get a warning.)Empty(..)
until #29383 lands, after that namespace it as in namespace::Empty
, or use Empty{}
(requires #![feature(braced_empty_structs)]
). (During the 1.6 beta you cannot use un-namespaced empty structs at all, because #29383 landed and broke this syntax, with no warning cycle. See #30379.)PAT
cannot be irrefutable. This is the same behavior as if let
and match
, and it's useless to write a guard with an irrefutable pattern anyway (you can just use let
), so this shouldn't be an issue. This is slightly more annoying than it could be due to limitation #1. Nonetheless, if #14252 is ever fixed, irrefutable patterns could be allowed by inserting a no-op pattern guard into the expansion.