-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
new lints around#[must_use]
#4560
Conversation
845f4af
to
a59abf3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just an initial review, I think this could use a second pair of eyes, too :)
Oh, and also a util/dev fmt
was missing
clippy_lints/src/functions.rs
Outdated
if let hir::ImplItemKind::Method(..) = item.node { | ||
self.depth = self.depth.saturating_sub(1); | ||
} | ||
} | ||
} | ||
|
||
impl<'a, 'tcx> Functions { | ||
fn check_arg_number(self, cx: &LateContext<'_, '_>, decl: &hir::FnDecl, span: Span) { | ||
// Remove the function body from the span. We can't use `SourceMap::def_span` because the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this comment can now be removed or should be moved to the doc comment of function_header_span
?
tests/ui/must_use_pure.stderr
Outdated
LL | pub fn pure(i: u8) -> u8 { | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn pure(i: u8) -> u8` | ||
| | ||
= note: `-D clippy::pure-without-must-use` implied by `-D warnings` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to have more pure function examples that trigger the lint. Does it trigger in pure trait methods, for example?
The error seems unrelated? Perhaps a Rust PR that changed the error output. |
Yup, that was fixed by #4565 |
a59abf3
to
a3912fe
Compare
I adressed your comments, @phansch. Thank you for the thorough review. |
a3912fe
to
134fac1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Impl LGTM. As @phansch said, a few more tests would be great. I think the code path of mutates_static() == true
is never hit by the tests?
134fac1
to
6145cf8
Compare
Added the tests and fixed the doc nit. |
6145cf8
to
901ecfd
Compare
I think this PR advocates a rather strange definition of "pure" which is not referentially transparent nor even deterministic. Looking at the diff it seems to have caused a non-trivial amount of false positives, e.g. involving file opening and such. Focusing on mutable types is also not enough, you need to consider side-effects though functions or basic things like |
Purity is – perhaps even in FP circles – a nebulous concept. Some people argue that it's about freedom from side effects (yet there is no such thing – any program running on a computer will burn cycles as a side effect, for example), others say they need to be referentially transparent or even deterministic. This lint takes a pragmatic approach. If a function does not mutate a static or its arguments, you'll likely want to call it for its result. I personally don't think file opening is a side effect I'd call a function for if I didn't want to do something with the file. Also I agree that the lint triggers on a lot of function. Can you point to some you consider false positives? |
This lint shouldn't apply to functions returning |
|
See https://pdfs.semanticscholar.org/32ff/28cb5b5c990fe7bdca510040ea22f5c13316.pdf for a well defined definition.
When reasoning about computer programs we do so preferably considering an idealized abstract machine in which some things (e.g. heat from burning cycles or bit flips due to radiation) are not observable. Otherwise it would be impossible to do all sorts of other reasonings as well (e.g. about soundness).
Referentially transparent is a common notion, but a basic property a pure function needs to satisfy is that given
That's fine; I would suggest renaming the lint to something more suggestive and to extend the "known problems" to note more false positives. In my view, a better, but still pragmatic solution would be to do this on MIR.
Merely opening a file is not an interesting side-effect (yet it might cause a problem if the file was already open), but reading it means you are reading the state of the world and that can result in indeterministic results. |
#[must_use]
on pure fns#[must_use]
on suitable fns
@phansch I've added your test case as-is and also added |
oh, yes! 😅
The test is just there to check that we don't lint occurences in external macros. It should still lint for non-external macros. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left two comments and I believe there are also two open comments from @sinkuu that are only visible in the changes tab?
Apart from that it looks good to me 👍
Let's see what CI thinks about it. I may need yet another rebase though. |
b9785b3
to
80f342b
Compare
`must_use_unit` lints unit-returning functions with a `#[must_use]` attribute, suggesting to remove it. `double_must_use` lints functions with a plain `#[must_use]` attribute, but which return a type which is already `#[must_use]`, so the attribute has no benefit. `must_use_candidate` is a pedantic lint that lints functions and methods that return some non-unit type that is not already `#[must_use]` and suggests to add the annotation.
@phansch r? |
@bors r+ nice! |
📌 Commit cc62260 has been approved by |
This comment has been minimized.
This comment has been minimized.
new lints around`#[must_use]` changelog: Add `must_use_candidate` lint, add `must-use-unit` lint, add `double_must_use` lint The first one checks if an public function or method has no mutable argument and mutates no non-local data and lints if it has no `#[must_use]` attribute. It will skip inner functions, because those are usually highly local and the attribute doesn't have as much benefit there. The second lints `#[must_use]` attributes on functions and methods that return unit. Those attributes are likely a remnant from a refactoring that removed the return value. The last one lints for `#[must_use]` attributrs without text on functions that return a type which is already marked `#[must_use]`. This has no auto-suggestion, because while it would be easy to do, there may be value in writing a detailed text for the attribute instead. This fixes #4526
This comment has been minimized.
This comment has been minimized.
new lints around`#[must_use]` changelog: Add `must_use_candidate` lint, add `must-use-unit` lint, add `double_must_use` lint The first one checks if an public function or method has no mutable argument and mutates no non-local data and lints if it has no `#[must_use]` attribute. It will skip inner functions, because those are usually highly local and the attribute doesn't have as much benefit there. The second lints `#[must_use]` attributes on functions and methods that return unit. Those attributes are likely a remnant from a refactoring that removed the return value. The last one lints for `#[must_use]` attributrs without text on functions that return a type which is already marked `#[must_use]`. This has no auto-suggestion, because while it would be easy to do, there may be value in writing a detailed text for the attribute instead. This fixes #4526
@bors retry |
new lints around`#[must_use]` changelog: Add `must_use_candidate` lint, add `must-use-unit` lint, add `double_must_use` lint The first one checks if an public function or method has no mutable argument and mutates no non-local data and lints if it has no `#[must_use]` attribute. It will skip inner functions, because those are usually highly local and the attribute doesn't have as much benefit there. The second lints `#[must_use]` attributes on functions and methods that return unit. Those attributes are likely a remnant from a refactoring that removed the return value. The last one lints for `#[must_use]` attributrs without text on functions that return a type which is already marked `#[must_use]`. This has no auto-suggestion, because while it would be easy to do, there may be value in writing a detailed text for the attribute instead. This fixes #4526
☀️ Test successful - checks-travis, status-appveyor |
Thanks, @phansch! |
changelog: Add
must_use_candidate
lint, addmust-use-unit
lint, adddouble_must_use
lintThe first one checks if an public function or method has no mutable argument and mutates no non-local data and lints if it has no
#[must_use]
attribute. It will skip inner functions, because those are usually highly local and the attribute doesn't have as much benefit there.The second lints
#[must_use]
attributes on functions and methods that return unit. Those attributes are likely a remnant from a refactoring that removed the return value.The last one lints for
#[must_use]
attributrs without text on functions that return a type which is already marked#[must_use]
. This has no auto-suggestion, because while it would be easy to do, there may be value in writing a detailed text for the attribute instead.This fixes #4526