# Swift-like guard statement

**URL:** <https://internals.rust-lang.org/t/swift-like-guard-statement/21646>\
**Category:** language design\
**Created:** [October 2, 2024, 12:53pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646 "2024-10-02T12:53:33Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![richr](https://avatars.discourse-cdn.com/v4/letter/r/b38774/32.png) [@richr](https://internals.rust-lang.org/u/richr)\
**Post date:** [October 2, 2024, 12:53pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/1 "2024-10-02T12:53:33Z")

</div>

(First post here - many apologies if this is not the best place for it!)

Rust has `let-else`, which is quite similar to Swift's `guard-let`, and which is something I use all the time.

But are there any plans to add something equivalent to a more general `guard` statement?

Basically the equivalent of:

```rust
if !some_condition {
    return // or continue if in a loop, or panic!(), etc
}

```

The difference being that `guard` enforces divergent / early return behaviour, in the same way that `let-else` does, and so carries some extra semantic meaning (and compiler checks) with it over the plain `if`. So this is kind of `let-else` but without the assignment aspect.

---

<div class="post-metadata">

**Author:** ![m-ronchi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/m-ronchi/32/11489_2.png) [@m-ronchi](https://internals.rust-lang.org/u/m-ronchi)\
**Post date:** [October 2, 2024, 1:37pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/2 "2024-10-02T13:37:53Z")

</div>

ugly, but

```rust
let true = some_condition else { return; };

```

works

---

<div class="post-metadata">

**Author:** ![afetisov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/afetisov/32/8508_2.png) [@afetisov](https://internals.rust-lang.org/u/afetisov)\
**Post date:** [October 2, 2024, 1:48pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/3 "2024-10-02T13:48:27Z")

</div>

[`anyhow`](https://docs.rs/anyhow/latest/anyhow/) has [`ensure!`](https://docs.rs/anyhow/latest/anyhow/macro.ensure.html) macro which does a similar thing (return `Err` if the condition fails). Other error-handling crates have similar functionality, and it's easy enough to write the relevant macro yourself. I don't see a reason to make it a language built-in syntax.

Similarly, `assert!` in the standard library serves the same purpose for `panic!()`.

Note that depending on your use case, you may want different behaviour in the divergent branch. Could be an early return, could be a `break` or `continue`. Imho the value-add of special syntax is thus quite low. If it's complex enough to cover all those use cases, it won't be particularly ergonomic, and if it isn't, you'd have to use different approaches anyway. Specifically in the case of early returns, a common case is returning `Err(Error::Variant)`. You'd generally want to abstract away the repeating `return Err(..);` part, but have some control over the construction of errors (which may themselves have some repeating part amenable to a macro).

---

<div class="post-metadata">

**Author:** ![richr](https://avatars.discourse-cdn.com/v4/letter/r/b38774/32.png) [@richr](https://internals.rust-lang.org/u/richr)\
**Post date:** [October 2, 2024, 2:27pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/4 "2024-10-02T14:27:30Z")

</div>

Thanks. I had thought I may have a go at creating a macro to do it but wasn't sure if I could cover all bases.

I've realised my sample code was probably far too basic, and probably should have looked something more like this:

```rust
if !some_condition {
    // potentially any extra logic here
    // ...
    // ...

    return // ultimately culminating in the compiler-enforced return/etc
}

```

Swift's syntax covers it fairly elegantly, but I can appreciate it may not be a good fit for Rust and that there are macro alternative that can essentially do the same thing.

Thanks for the pointers and reading material!

---

<div class="post-metadata">

**Author:** ![richr](https://avatars.discourse-cdn.com/v4/letter/r/b38774/32.png) [@richr](https://internals.rust-lang.org/u/richr)\
**Post date:** [October 2, 2024, 2:29pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/5 "2024-10-02T14:29:53Z")

</div>

This is quite interesting actually!

Might take a while for my eyes to get used to it, but it ticks the box - thanks!

---

<div class="post-metadata">

**Author:** ![jdahlstrom](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdahlstrom/32/3351_2.png) [@jdahlstrom](https://internals.rust-lang.org/u/jdahlstrom)\
**Post date:** [October 2, 2024, 2:53pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/6 "2024-10-02T14:53:25Z")

</div>

The Perlish pattern

```rust
some_condition || return;

```

works as well, though it generates a warning about an unused value. YMMV whether it’s ugly or not.

---

<div class="post-metadata">

**Author:** ![richr](https://avatars.discourse-cdn.com/v4/letter/r/b38774/32.png) [@richr](https://internals.rust-lang.org/u/richr)\
**Post date:** [October 2, 2024, 3:36pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/7 "2024-10-02T15:36:16Z")

</div>

Wrapping that up in a (possibly?) easier on the eye macro seems to be working quite nicely for me now:

```rust
macro_rules! guard_else {
    ($condition:expr, $body:block) => {
        let true = $condition else { $body };
    };
}

```

and to give a hideously contrived example:

```rust
for i in 1..=100 {
    guard_else!(i < 10, {
        // Arbitrary logic here...
        println!("DONE");
        break; // Compiler complains if this is missing (which is good!)
    });
    // ...
 }

```

This is very close to what I was originally envisaging and in very little code. Thank for the insight on using `let-else` in that way!

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [October 4, 2024, 7:21pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/8 "2024-10-04T19:21:43Z")

</div>

Rust already has `if let` (soon hopefully with multiple `let`) and `let else`, and I think further combos of these are more and more niche, and overload the syntax more and more.

After using `let else` for a while, I'm not even that enthusiastic about it any more, because I often find that I do want to inspect the error, and have to change to a `match` anyway (and all the proposal to add extra patterns to `let else` look like `match` with some randomized syntax order).

The `if !condition { return }` construct is as old as `if` and `return`, so inventing something new for it would be adding weirdness to the language. Maybe `?` could be implemented on `bool` 🙂

---

<div class="post-metadata">

**Author:** ![richr](https://avatars.discourse-cdn.com/v4/letter/r/b38774/32.png) [@richr](https://internals.rust-lang.org/u/richr)\
**Post date:** [October 5, 2024, 3:31am UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/9 "2024-10-05T03:31:23Z")

</div>

Thanks, this is an interesting take for sure and does give me pause for thought.

`guard` in Swift is generally considered to be an extremely useful tool for early returns (and similar), and avoiding deeply nested conditions - but I can certainly appreciate that Rust is not Swift and that this just might not be a good fit.

My experience currently lies more on the Swift end of the “Rustometer” after working with it for nearly a decade, so I probably need to fully internalize the Rust way of doing things a little more. It might well be I end up favouring `match` over `let else` after another 6 months perhaps!

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [October 5, 2024, 6:25pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/10 "2024-10-05T18:25:58Z")

</div>

> [@kornel](#):
>
> The `if !condition { return }` construct is as old as `if` and `return`, so inventing something new for it would be adding weirdness to the language.

TBH, I wish we'd done `unless` instead of `let`-`else`, since I'm also finding myself more and more saddened by let-else. Notably, when there's a whole bunch of `let`s that all have `else { continue };` or similar, I wish there was something better.

```rust
unless let Some(x) = y
    && let Some(z) = x.blah()
    && z >= 0
{
    return None;
}

```

would have chained better, and could have kept the "body must diverge" property to give it a reason to exist over just `if !`.

(But who knows, maybe we'll be allowed to put chains in `let` one day for that use, sharing an `else`. That'll still be weird for any conditions that _aren't_ a `let`, though.)

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [October 5, 2024, 7:32pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/11 "2024-10-05T19:32:24Z")

</div>

> [@scottmcm](#):
>
> (But who knows, maybe we'll be allowed to put chains in `let` one day for that use, sharing an `else`. That'll still be weird for any conditions that _aren't_ a `let`, though.)

I've always found it funny to imagine allowing pattern-guards in let-else

```rust
let Some(x) = y && let (Some(z) if z >= 0) = x.blah() else {
    return None;
}

```

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [October 5, 2024, 7:34pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/13 "2024-10-05T19:34:51Z")

</div>

> [@scottmcm](#):
>
> (But who knows, maybe we'll be allowed to put chains in `let` one day for that use, sharing an `else`. That'll still be weird for any conditions that _aren't_ a `let`, though.)

IIRC, it’s exactly for that possibility that `&&` used directly in `let else` is currently [_not_](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=a4ba5157edae9231898a765cff287259) allowed.

```rust
let x = true && false else { … };

```

```plaintext
error: a `&&` expression cannot be directly assigned in `let...else`
 --> src/lib.rs:2:13
  |
… | let x = true && false else { … };
  | ^^^^^^^^^^^^^
  |
help: wrap the expression in parentheses
  |
… | let x = (true && false) else { … };
  | + +

```

* * *

Or was that just because it was considered somehow potentially confusing?

* * *

_Edit:_ Indeed let-chains were are mentioned as future possibilities in the `let … else` RFC. A `let … else match` is also mentioned, by the way.

[https://rust-lang.github.io/rfcs/3137-let-else.html#future-possibilities](https://rust-lang.github.io/rfcs/3137-let-else.html#future-possibilities)

---

<div class="post-metadata">

**Author:** ![curoli](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/curoli/32/11357_2.png) [@curoli](https://internals.rust-lang.org/u/curoli)\
**Post date:** [October 8, 2024, 8:18pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/14 "2024-10-08T20:18:43Z")

</div>

Sorry, but I got to ask: Are you familiar with the [`?`](https://doc.rust-lang.org/rust-by-example/std/result/question_mark.html) operator?

---

<div class="post-metadata">

**Author:** ![richr](https://avatars.discourse-cdn.com/v4/letter/r/b38774/32.png) [@richr](https://internals.rust-lang.org/u/richr)\
**Post date:** [October 9, 2024, 1:57am UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/15 "2024-10-09T01:57:35Z")

</div>

Yes thanks but I’m not sure it enables the kind of patterns I had in mind, particularly to do with running arbitrary (and local) code prior to the early return from a function or break/continue in a loop

---

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [October 11, 2024, 12:37pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/16 "2024-10-11T12:37:53Z")

</div>

Could someone point to a representative example of what the `guard` statement even looks like? Seems like the entire thread is filled with people that already know Swift or something, since there's not a single example showing the suggested syntax. 😉

---

<div class="post-metadata">

**Author:** ![richr](https://avatars.discourse-cdn.com/v4/letter/r/b38774/32.png) [@richr](https://internals.rust-lang.org/u/richr)\
**Post date:** [October 11, 2024, 2:39pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/17 "2024-10-11T14:39:30Z")

</div>

I'm not at my main computer right now and this code may not actually compile (although it should hopefully be close enough to give an idea). It's also super contrived and folks likely wouldn't write code quite like this - for basic illustration purposes only!

```rust
func doSomething(var1: Double) -> SomeType {
    // guard-ing a Boolean condition
    guard var1 > 0 else {
        // Any arbitrary code can go here, for example:
        print("var1 must be greater than 0")
        // ...etc...
        return // The compiler will complain if this return is missing - the body of the guard must diverge
    }

    // guard-ing an assignment with let (similar to Rust's let-else)
    guard let var2 = someFunc() else {
        // As above
        print("var2 could not be computed")
        return
    }

    // "Happy path" here
    // ...etc...
}

```

Basically, the `guard` statement provides a clean, compiler-checked way to do early returns (and more). You'll often see it mentioned with reference to "avoiding the pyramid of doom" and "keeping the happy path to the left".

It can result in flatter-looking functions that can be more readable than their deeply-nested counterparts.

You can of course fairly much do exactly the same thing using plain old `if` but the nice thing about `guard` is that the compiler will ensure you you are diverging - such as via the `return`s in the above example. So you can't accidentally forget to include the `return` like you could with an `if` condition that's attempting to return early.

`guard` also works in analogous ways inside of loops - for example, you'd test some kind of condition at the start of the loop and then `break` or `continue` if it's not met (again, the compiler would ensure you do this), and then the main body of the loop is free to assume all the problem code is out of the way with.

I'm not sure if that explains it well enough? It's kind of `if...return` with extra compiler checks, or alternatively it can be thought of as `let-else` but more general.

It's this more general alternative to `let-else` that I was originally enquiring about, and @m-ronchi 's [suggestion above](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/2) actually gets me pretty close. Although to cut a long story short it might all come down to me needing to lean into Rust's idioms more and forget about this whole business! Especially with some folks mentioning above that they're not actually fans of `let-else` in Rust.

---

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [October 11, 2024, 2:57pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/18 "2024-10-11T14:57:11Z")

</div>

That helps, thanks. So it indeed seems fully equivalent to this, then (which has been suggested above):

```rust
let true = condition else {
  // Code goes here. Compiler ensures you are diverging on this branch.
};

```

The Rust version looks really strange, but is not actually that much more verbose than `guard` -- it's literally `let true =` vs `guard`.

In your 2nd example, what is the return type of `someFunc()`? Is it the equivalent of `Option<T>` and this the same as `let Some(var2) = someFunc() else { ... }`, just somehow with `Some` being implicit?

You say this comes "pretty close", what is the remaining difference?

> [@richr](#):
>
> Especially with some folks mentioning above that they're not actually fans of `let-else` in Rust.

FWIW I quite like it. 🤷

---

<div class="post-metadata">

**Author:** ![richr](https://avatars.discourse-cdn.com/v4/letter/r/b38774/32.png) [@richr](https://internals.rust-lang.org/u/richr)\
**Post date:** [October 11, 2024, 4:17pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/19 "2024-10-11T16:17:32Z")

</div>

Yep that’s right re: the second example, exactly.

And really I think by “pretty close” I was just talking about the slightly strange syntax involved with the Rust version, which almost (to me) feels like an abuse of the `let` statement. But other than that it’s really the same thing, yeah. I think I just need to look at it a few more times to appreciate its beauty!

And I’m glad to hear there’s somebody else out there that quite likes let-else! Thank you!

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [April 4, 2026, 4:17pm UTC](https://internals.rust-lang.org/t/swift-like-guard-statement/21646/20 "2026-04-04T16:17:54Z")

</div>

This topic was automatically closed 540 days after the last reply. New replies are no longer allowed.
