# Enable linting for implicit returns

**URL:** <https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170>\
**Category:** help\
**Created:** [July 19, 2023, 6:15am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170 "2023-07-19T06:15:09Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![mcmuffin6o](https://avatars.discourse-cdn.com/v4/letter/m/9f8e36/32.png) [@mcmuffin6o](https://users.rust-lang.org/u/mcmuffin6o)\
**Post date:** [July 19, 2023, 6:15am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/1 "2023-07-19T06:15:09Z")

</div>

How do I enable linting for explicit returns? I hate them, and I don't understand why they're valid syntax in the first place. Is it really going to kill someone to type six characters and a space? They just seem like a needless way to make Rust code more confusing to read.

I understand that removing them from the language would break some things, so we unfortunately cannot purge the language of this nonsense, but I pray that I can at least make sure that such an insidious mechanism never finds its way into my codebase.

---

<div class="post-metadata">

**Author:** ![H2CO3](https://avatars.discourse-cdn.com/v4/letter/h/b5ac83/32.png) [@H2CO3](https://users.rust-lang.org/u/H2CO3)\
**Post date:** [July 19, 2023, 6:21am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/2 "2023-07-19T06:21:03Z")

</div>

> [@mcmuffin6o](#):
>
> Is it really going to kill someone to type six characters and a space? They just seem like a needless way to make Rust code more confusing to read.

What you think is an implicit "return" isn't a return at all, ie. it doesn't alter control flow.

Rust is an expression language, and blocks evaluate to their last expression. This is true for a function body too, that's all. What you think of as a special case in fact fits very well with the rest of the language.

> [@mcmuffin6o](#):
>
> so we unfortunately cannot purge the language of this nonsense, but I pray that I can at least make sure that such an insidious mechanism

That was completely unnecessary. If you don't understand the language well enough to be able to formulate an informed opinion about it, then better not start a rant about it. Have some humility and learn before whining.

---

<div class="post-metadata">

**Author:** ![vague](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/vague/32/21401_2.png) [@vague](https://users.rust-lang.org/u/vague)\
**Post date:** [July 19, 2023, 6:22am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/3 "2023-07-19T06:22:32Z")

</div>

> [@mcmuffin6o](#):
>
> How do I enable linting for explicit returns?

[`#![deny(clippy::implicit_return)]`](https://rust-lang.github.io/rust-clippy/stable/index.html#implicit_return)

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/scottmcm/32/4286_2.png) [@scottmcm](https://users.rust-lang.org/u/scottmcm)\
**Post date:** [July 19, 2023, 6:25am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/4 "2023-07-19T06:25:45Z")

</div>

> [@mcmuffin6o](#):
>
> I don't understand why they're valid syntax in the first place.

They're the same as how in Rust we idiomatically write

```rust
let x = if b { 7 } else { 13 };

```

rather than

```rust
let x;
if b {
    x = 7;
} else {
    x = 13;
}

```

---

<div class="post-metadata">

**Author:** ![mcmuffin6o](https://avatars.discourse-cdn.com/v4/letter/m/9f8e36/32.png) [@mcmuffin6o](https://users.rust-lang.org/u/mcmuffin6o)\
**Post date:** [July 19, 2023, 6:39am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/5 "2023-07-19T06:39:38Z")

</div>

I don't think I need to be an expert on Rust to have an opinion on it. It's widely known that Rust has its gatekeepers, but I find it kind of hilarious that they will go so far as to _gatekeep the very act of having an opinion_.

It's undeniable that implicit returns make code more confusing to read in many instances. On the other hand, no one has shown me where explicit returns make code prohibitively verbose. Do you have an example of some code that would be miserable to write if it required explicit `return` statements?

I'm happy to learn -- you just need to have something valuable to teach.

---

<div class="post-metadata">

**Author:** ![Cerber-Ursi](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/cerber-ursi/32/8315_2.png) [@Cerber-Ursi](https://users.rust-lang.org/u/Cerber-Ursi)\
**Post date:** [July 19, 2023, 6:44am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/6 "2023-07-19T06:44:31Z")

</div>

> [@mcmuffin6o](#):
>
> It's undeniable that implicit returns make code more confusing to read in many instances.

...for the people who haven't yet got an experience with it and haven't yet built an intuition for the whole "blocks are values" thing, which is used much more widely then just "implicit returns". For the ones who have, this "undeniable" sounds like at least an exaggeration.

---

<div class="post-metadata">

**Author:** ![mcmuffin6o](https://avatars.discourse-cdn.com/v4/letter/m/9f8e36/32.png) [@mcmuffin6o](https://users.rust-lang.org/u/mcmuffin6o)\
**Post date:** [July 19, 2023, 6:46am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/7 "2023-07-19T06:46:05Z")

</div>

> [@scottmcm](#):
>
> `let x = if b { 7 } else { 13 };`

It's unclear as to why we need those braces in the first place. An assignment requiring more than a single expression would seem like code smell to me.

> [@Cerber-Ursi](#):
>
> blocks are values

Well put. This makes sense to me, and I can understand why implicit returns exist now. I still don't think they belong in a `fn` block, but now it's clear why it's valid syntax. I suppose this is where linters come in!

> [@Cerber-Ursi](#):
>
> For the ones who have, this "undeniable" sounds like at least an exaggeration.

Fair enough -- go ahead and replace "It's undeniable that..." with "To the novice, it seems that..."

---

<div class="post-metadata">

**Author:** ![abdavis](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/abdavis/32/47765_2.png) [@abdavis](https://users.rust-lang.org/u/abdavis)\
**Post date:** [July 19, 2023, 7:07am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/8 "2023-07-19T07:07:04Z")

</div>

> [@mcmuffin6o](#):
>
> > [@scottmcm](#):
> >
> > `let x = if b { 7 } else { 13 };`
> 
> It's unclear as to why we need those braces in the first place. An assignment requiring more than a single expression would seem like code smell to me.

Those braces are necessary to disambiguate between the condition and the expression. The alternative would look something like `let x = if b 7 else 15;`, which looks way more confusing to me. It could get even worse:  
`let x = if b >= 5 && a != 0 c || d else false;`  
As opposed to  
`let x = if b >= 5 && a != 0 {c || d} else {false};`

So really, I don't see how this could work without the braces.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/scottmcm/32/4286_2.png) [@scottmcm](https://users.rust-lang.org/u/scottmcm)\
**Post date:** [July 19, 2023, 7:09am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/9 "2023-07-19T07:09:41Z")

</div>

> [@mcmuffin6o](#):
>
> An assignment requiring more than a single expression would seem like code smell to me.

Why would you think that? Most languages have something like this, though often they spell it differently -- `x = b ? 7 : 13;` in C, for example.

> [@mcmuffin6o](#):
>
> but I find it kind of hilarious that they will go so far as to _gatekeep the very act of having an opinion_.

Rust is what it is, and some parts of it just aren't changing. Like people can have the opinion that languages are better with significant whitespace and no semicolons, but that's not an option that's _useful_ to share in a Rust forum, since there's no way it's changing for Rust.

"Why doesn't this language A look like what I'm used to in language B? I hate it." isn't a productive discussion for any language pair.

If you want positive engagement, I suggest conveying curiosity and openness, and avoiding "hate", "kill someone", "needless", "nonsense", "insidious", etc.

---

<div class="post-metadata">

**Author:** ![HJVT](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/hjvt/32/31640_2.png) [@HJVT](https://users.rust-lang.org/u/HJVT)\
**Post date:** [July 19, 2023, 7:19am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/10 "2023-07-19T07:19:05Z")

</div>

> [@mcmuffin6o](#):
>
> Fair enough -- go ahead and replace "It's undeniable that..." with "To the novice, it seems that..."

Well that's also not entirely right.  
There are a lot of expression-based languages that have "implicit return". From Lisp, to Ruby to Haskell, people coming from those languages will feel right at home with rust's expressionist nature.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/steffahn/32/47569_2.png) [@steffahn](https://users.rust-lang.org/u/steffahn)\
**Post date:** [July 19, 2023, 9:24am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/11 "2023-07-19T09:24:30Z")

</div>

In Rust, the `return` keyword is used for _early_ returns, since it has the ability to exit the normal control flow of evaluation early.

In many other languages, this distinction is only made for cases where no values are returned.

For example in a for loop, one would usually _not_ write

```rust
for i in some_collection() {
    if foo(i) {
        do_something();
    else {
        do_something_else();
    }
    let var = calc(i);
    var.method().another_method();
    continue;
}

```

instead, one would typically let the loop do an _implicit_ `continue;` at the end of the loop body. The `continue;` statement would only be used for early-`continue`, like in:

```rust
for i in some_collection() {
    if foo(i) {
        do_something();
        continue;
    }
    let var = calc(i);
    var.method().another_method();
}

```

* * *

As far as I’m aware, the same is typically true for `return` in functions without a return value, too. I’ll still use Rust syntax, but think how you’d do it in C (honestly, I never used C or C++ too much, so I wouldn’t know what’s _actually_ idiomatic):

One wouldn’t write

```rust
fn foo(i: Foo) {
    if foo(i) {
        do_something();
    else {
        do_something_else();
    }
    let var = calc(i);
    var.method().another_method();
    return;
}

```

but instead

```rust
fn foo(i: Foo) {
    if foo(i) {
        do_something();
    else {
        do_something_else();
    }
    let var = calc(i);
    var.method().another_method();
}

```

however, `return;` is useful as an _early_ `return` as in

```rust
fn foo(i: Foo) {
    if foo(i) {
        do_something();
        return;
    }
    let var = calc(i);
    var.method().another_method();
}

```

* * *

Even with `if` expressions at the end of a function (or a loop body), there’s an analogy, that one wouldn’t write

```rust
fn foo(i: Foo) {
    if foo(i) {
        do_something();
        return;
    } else {
        do_something_else();
        return;
    }
}

```

and there’s an argument to be had whether

```rust
fn foo(i: Foo) {
    if foo(i) {
        do_something();
    } else {
        do_something_else();
    }
}

```

or

```rust
fn foo(i: Foo) {
    if foo(i) {
        do_something();
        return;
    }
    do_something_else();
}

```

is nicer (the latter _can_ be better if in place of `do_something_else()`) there is a long and/or nested piece of code, and/or the `do_something_else()` case is some standard case whereas `do_something` is exceptional, doing validation and early-returning an error, for instance.

* * *

Now with Rust’s expression based syntax, we do have a way to transfer all these considerations to returns _with_ values, too. `return EXPR;` can serve the role of being used only in early returns, and using a trailing `EXPR` (without semicolon) at the end of any block specifies a return value (of the block, which might thus also become the return value of the whole function).

The example code could thus, very analogously look as follows:

We don’t write

```rust
fn foo(i: Foo) {
    if foo(i) {
        do_something();
        return fallback();
    } else {
        do_something_else();
        return i;
    }
}

```

but

```rust
fn foo(i: Foo) {
    if foo(i) {
        do_something();
        fallback()
    } else {
        do_something_else();
        i
    }
}

```

and there’s an argument to be had, depending on the specific code at hand, whether

```rust
fn foo(i: Foo) {
    if foo(i) {
        do_something();
        return fallback();
    }
    do_something_else();
    i
}

```

might be preferred.

With these comparison explained in detail, I’d finally like to argue against your strawman “Is it really going to kill someone to type six characters and a space?”

### In my view, the _main_ advantage of “implicit returns”(1) is _not at all_ that one saves a few keystrokes, but instead that the ‘`return`’ keyword thus becomes a keyword for explicit _early_ returns, similar to how ‘`continue`’ is a keyword for jumping _early_ to the next iteration of a loop.

(1) which arguably are _not_ actually implicit, but rather just “`return`”-keyword-less

This means that in idiomatic Rust codebases, the `return` keyword, along with the `?` operator, serves as a well visible mark for more complicated control flow paths, and a lack or `return` and `?` means at a glance that (ignoring unwinding) control flow is very structured and straightforward.

---

<div class="post-metadata">

**Author:** ![mcmuffin6o](https://avatars.discourse-cdn.com/v4/letter/m/9f8e36/32.png) [@mcmuffin6o](https://users.rust-lang.org/u/mcmuffin6o)\
**Post date:** [July 19, 2023, 12:27pm UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/12 "2023-07-19T12:27:23Z")

</div>

All good points, save for the first -- I don't think I've ever seen/heard someone speak positively of the ternary operator.

---

<div class="post-metadata">

**Author:** ![mcmuffin6o](https://avatars.discourse-cdn.com/v4/letter/m/9f8e36/32.png) [@mcmuffin6o](https://users.rust-lang.org/u/mcmuffin6o)\
**Post date:** [July 19, 2023, 12:33pm UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/13 "2023-07-19T12:33:30Z")

</div>

Both of those two additional examples contain smelly code in my opinion. I feel like there's gotta be a way to avoid the necessity for the original example of `let x = if b { 7 } else { 13 };` in the first place. Besides that, those two additional examples make the case for explicit returns -- try the following:

```plaintext
let x = if b >= 5 && a != 0 return c || d else return false;

```

Again, though, I feel like it would be best to avoid the ternary operator or any syntactic sugar for it.

---

<div class="post-metadata">

**Author:** ![tczajka](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/tczajka/32/24743_2.png) [@tczajka](https://users.rust-lang.org/u/tczajka)\
**Post date:** [July 19, 2023, 12:56pm UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/14 "2023-07-19T12:56:53Z")

</div>

> [@mcmuffin6o](#):
>
> ```rust
> let x = if b >= 5 && a != 0 return c || d else return false;
> 
> ```

This code (after you add the missing braces) doesn't do what you think it does. The `return` expression **exits the function**. This would never assign anything to `x`.

---

<div class="post-metadata">

**Author:** ![burjui](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/burjui/32/7562_2.png) [@burjui](https://users.rust-lang.org/u/burjui)\
**Post date:** [July 24, 2023, 10:57pm UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/15 "2023-07-24T22:57:23Z")

</div>

Writing `return <something>;` at the end of a function in Rust is a bit like answering the question "Do you like potatoes?" with "Yes, I like potatoes" instead of simple "Yes".

---

<div class="post-metadata">

**Author:** ![Cyborus](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/cyborus/32/34148_2.png) [@Cyborus](https://users.rust-lang.org/u/Cyborus)\
**Post date:** [July 25, 2023, 1:31am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/16 "2023-07-25T01:31:57Z")

</div>

This could be ambiguous to parse, too, considering closures:

```rust
let f = if a || b else || c;
// vs
let f = if a { || b } else { || c };

```

---

<div class="post-metadata">

**Author:** ![jjpe](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/jjpe/32/28767_2.png) [@jjpe](https://users.rust-lang.org/u/jjpe)\
**Post date:** [July 25, 2023, 2:25am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/17 "2023-07-25T02:25:08Z")

</div>

> [@mcmuffin6o](#):
>
> All good points, save for the first -- I don't think I've ever seen/heard someone speak positively of the ternary operator.

I suspect you've mostly been using languages like C/C++, Java, C# etc i.e. non-expression-based languages that have a ternary operator.  
In those languages the operator works, but is a bit like a fish out of water in terms of UX when compared to the rest of the language.

Rust is different from those languages in that Rust is expression-based to the bone.  
Making if/else a statement rather than an expression would have been a major mistake given the expression-orientation of the language. And the real difference between what's called the ternary operator in C/C++, Java etc and the if/else expression in Rust is syntactic, not semantic.

> [@mcmuffin6o](#):
>
> I _feel_ like there's gotta be a way to avoid the necessity for the original example of `let x = if b { 7 } else { 13 };` in the first place.

If I may, perhaps it's your feelings standing in the way here. What if you put those aside for just a moment, and reflected on this:

Whether something, anything, is a code smell, is largely dependent on the semantics of the surrounding context, mainly the rest of the programming language. For example, this is a code smell in Java:

```rust
if (mystr == "hello") {
    //... 
}

```

But the direct equivalent code in Rust (i.e. same without the parens surrounding the predicate) is not. The reason for that comes down to how each language handles references. In Rust borrows are valid, period, while in Java any reference can be `null`, leading to either a longer, noisier predicate that's prefixed with a nullptr check, or [Yoda conditions](https://en.m.wikipedia.org/wiki/Yoda_conditions).

---

<div class="post-metadata">

**Author:** ![riking](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/riking/32/2351_2.png) [@riking](https://users.rust-lang.org/u/riking)\
**Post date:** [July 25, 2023, 7:00am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/18 "2023-07-25T07:00:12Z")

</div>

> [@jjpe](#):
>
> But the direct equivalent code in Rust (i.e. same without the parens surrounding the predicate) is not. The reason for that comes down to how each language handles references. In Rust borrows are valid, period, while in Java any reference can be `null`, leading to either a longer, noisier predicate that's prefixed with a nullptr check, or [Yoda conditions](https://en.m.wikipedia.org/wiki/Yoda_conditions).

It's also bad for an entirely different reason you seem to have missed: in Java, the `==` operator compares object addresses, while in Rust PartialEq recurses through references to compare values.

String constants may or may not be separate objects due to the vagaries of dynamic construction, interning, and multiple `ClassLoader`s. (Similarly in Rust with `&'static str` due to string deduplication, compilation units, and dynamic loading.)

---

<div class="post-metadata">

**Author:** ![jjpe](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/jjpe/32/28767_2.png) [@jjpe](https://users.rust-lang.org/u/jjpe)\
**Post date:** [July 25, 2023, 7:11am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/19 "2023-07-25T07:11:38Z")

</div>

While you're right about all of that, it wasn't important to my point, so I left it out.

---

<div class="post-metadata">

**Author:** ![mcmuffin6o](https://avatars.discourse-cdn.com/v4/letter/m/9f8e36/32.png) [@mcmuffin6o](https://users.rust-lang.org/u/mcmuffin6o)\
**Post date:** [July 31, 2023, 12:00am UTC](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170/20 "2023-07-31T00:00:20Z")

</div>

We were speaking in hypotheticals... I made no claim as to the validity of my snippet. It was pseudocode for discussion purposes. It's worth noting that such a statement really isn't easy on the eyes any way you put it.

In cases where you really need a one-liner, I think Python does the best job by phrasing it as

```plaintext
x = c || d if b >= 5 && a != 0 else x = false

```

The confusing bit (that probably shouldn't be a one-liner) is now trapped between an `if` and an `else` with nowhere to hide and no way to make things confusing!

[Next page](https://users.rust-lang.org/t/enable-linting-for-implicit-returns/97170.md?page=2)
