# Lint for unused return values of "pure" functions

**URL:** https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435
**Category:** tools and infrastructure
**Created:** [February 13, 2019, 7:47pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435 "2019-02-13T19:47:30Z")
**Posts on this page:** 18
**Page:** 1

<div class="post-metadata">

### Author: ![BatmanAoD](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/batmanaod/32/1512_2.png) [@BatmanAoD](https://internals.rust-lang.org/u/BatmanAoD)
#### Post date: [February 13, 2019, 7:47pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/1 "2019-02-13T19:47:30Z")

</div>

I was recently caught by surprise when I tried to use `f64::round()` to _mutate_ the receiver:

```
value.round();

```

…of course, what I should have written was:

```
value = value.round();

```

This was admittedly a “dumb” mistake, but I was surprised that `round()` isn’t marked `#[must_use]`, so I didn’t get a warning.

Even so, this seems like something Clippy could catch, but currently, [it doesn’t](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=6b54b5fecbe94dd3b201f07d97debeba). For functions where all of the arguments are by-shared-reference or by-copy, and a value is returned, it seems likely to be a bug if the value is ignored.

Does treating such “pure” functions1 as automatically `#[must_use]` seem like a good idea for a lint? If so, should I just go ahead and try to implement it in Clippy and submit it as a pull request?

1 I realize that Rust does not have a formal definition of “pure” functions, and that there’s not really a standard definition that could be easily applied. My suggestion for this lint is to ignore I/O and simply use mutability to determine whether a function is “pure”.

---

<div class="post-metadata">

### Author: ![felix.s](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/felix.s/32/8073_2.png) [@felix.s](https://internals.rust-lang.org/u/felix.s)
#### Post date: [February 13, 2019, 7:58pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/2 "2019-02-13T19:58:08Z")

</div>

Has been proposed before:

> <https://github.com/rust-lang/rfcs/pull/2450>

---

<div class="post-metadata">

### Author: ![BatmanAoD](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/batmanaod/32/1512_2.png) [@BatmanAoD](https://internals.rust-lang.org/u/BatmanAoD)
#### Post date: [February 13, 2019, 8:01pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/3 "2019-02-13T20:01:44Z")

</div>

Looks like work was abandoned because there was no one to spearhead it, and the proposal ran into some issues by assuming that `const fn` is necessarily “pure”. My proposal overlaps with that one, but isn’t identical (and explicitly wouldn’t run into the same issue with `Drop`, since I specified that it would _only_ apply to functions where the arguments are either `&` or `Copy`).

Should I just open a new RFC?

---

<div class="post-metadata">

### Author: ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)
#### Post date: [February 13, 2019, 8:42pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/4 "2019-02-13T20:42:39Z")

</div>

Note that [`&_` is `Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html#impl-Copy-63) as well.

I’m pretty sure that `clippy` would accept a `pedantic` lint for “immediately discarded return value from function taking only `Copy` arguments”.

---

<div class="post-metadata">

### Author: ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)
#### Post date: [February 13, 2019, 9:01pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/5 "2019-02-13T21:01:00Z")

</div>

This is not strong enough to say “this is a pure function”; consider a function that takes no arguments and locks a global, not-RAII mutex in a system library.

---

<div class="post-metadata">

### Author: ![dhm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhm/32/4879_2.png) [@dhm](https://internals.rust-lang.org/u/dhm)
#### Post date: [February 13, 2019, 9:09pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/6 "2019-02-13T21:09:07Z")

</div>

Excluding the `()`, this sounds like a very decent lint, but some “pure” false positives remain:

- aliasing does not always imply immutability. Take, for instance, [`::std::sync::atomic::AtomicUsize::fetch_add`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_add) ;
- some form of unfallible global state, like a global mutable var (using `unsafe` or inner mutability), or printing to `stdout` through its panicking version (e.g. `print[ln]!`)

---

<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: [February 13, 2019, 9:09pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/7 "2019-02-13T21:09:12Z")

</div>

You might be interested in the discussion on this issue:

> <https://github.com/rust-lang/rust/issues/48926#issuecomment-386931446>

---

<div class="post-metadata">

### Author: ![BatmanAoD](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/batmanaod/32/1512_2.png) [@BatmanAoD](https://internals.rust-lang.org/u/BatmanAoD)
#### Post date: [February 13, 2019, 9:59pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/8 "2019-02-13T21:59:57Z")

</div>

> [@mcy](#):
>
> This is not strong enough to say “this is a pure function”...

That's why I included the caveat about the term "pure".

> [@dhm](#):
>
> ...some “pure” false positives remain

I understand; but return values are easy enough to _explicitly_ ignore (`let _ = `) that I personally don't really think false positives are a problem. Of course, that's purely a matter of opinion.

---

<div class="post-metadata">

### Author: ![dhm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhm/32/4879_2.png) [@dhm](https://internals.rust-lang.org/u/dhm)
#### Post date: [February 13, 2019, 10:33pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/9 "2019-02-13T22:33:01Z")

</div>

> [@BatmanAoD](#):
>
> return values are easy enough to _explicitly_ ignore ( `let _ =` )

Good point

---

<div class="post-metadata">

### Author: ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)
#### Post date: [February 14, 2019, 4:04pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/10 "2019-02-14T16:04:41Z")

</div>

It seems much more achievable to tag some of these specific functions in std that are liable to be mis-used as methods as `#[must_use]` now that we have that feature on functions.

---

<div class="post-metadata">

### Author: ![BatmanAoD](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/batmanaod/32/1512_2.png) [@BatmanAoD](https://internals.rust-lang.org/u/BatmanAoD)
#### Post date: [February 14, 2019, 8:28pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/11 "2019-02-14T20:28:31Z")

</div>

You’re probably already aware, but that’s the main topic in the GitHub issue thread above. One complaint about that is that the annotations are noisy, which is true.

---

<div class="post-metadata">

### Author: ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)
#### Post date: [February 14, 2019, 9:03pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/12 "2019-02-14T21:03:50Z")

</div>

I think the standard library is doomed to noisy attributes by its place in the ecosystem (we’ve already committed to a stable/unstable attribute on every single item). I don’t think we should put a must\_use on every “pure” function; I think we should put them on ones that seem plausible to mistake as mutating methods (like round). And that’s something we can do _now_, whereas these kinds of abstractions run into problems around fuzziness as we’ve seen before we even get into bothering to implement them.

---

<div class="post-metadata">

### Author: ![BatmanAoD](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/batmanaod/32/1512_2.png) [@BatmanAoD](https://internals.rust-lang.org/u/BatmanAoD)
#### Post date: [February 14, 2019, 10:02pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/13 "2019-02-14T22:02:52Z")

</div>

Fair enough. So would the appropriate action be to just start opening PRs that add such annotations?

---

<div class="post-metadata">

### Author: ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)
#### Post date: [February 14, 2019, 11:47pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/14 "2019-02-14T23:47:01Z")

</div>

I’d certainly love to see such PRs.

---

<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: [February 15, 2019, 12:01am UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/15 "2019-02-15T00:01:23Z")

</div>

That’s how I got some added 🙂 I’d suggest picking a theme to justify why those particular ones.

> <https://github.com/rust-lang/rust/pull/49533>

---

<div class="post-metadata">

### Author: ![Finn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/finn/32/3841_2.png) [@Finn](https://internals.rust-lang.org/u/Finn)
#### Post date: [February 15, 2019, 12:22pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/16 "2019-02-15T12:22:39Z")

</div>

It might have been better if `#[must_use]` would be the default for other types than `()`. Now I wonder how often people intentionally allow return values to be implicitly discarded.

---

<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: [February 15, 2019, 12:27pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/17 "2019-02-15T12:27:02Z")

</div>

If you want to see how annoying this is go to a crate and run `RUSTFLAGS='-W unused-results' cargo build`, I have tried having this enabled on projects in the past and found it to be too noisy to be worth doing.

---

<div class="post-metadata">

### Author: ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)
#### Post date: [May 16, 2019, 12:27pm UTC](https://internals.rust-lang.org/t/lint-for-unused-return-values-of-pure-functions/9435/18 "2019-05-16T12:27:03Z")

</div>

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