Not a fan of semicolon_if_nothing_returned
#13198
Replies: 1 comment
-
You pointed out a lot of reasons why the For me, if I read fn handle_foo(req: Request) { // Might be off-screen, if the function is long
// ...
req.resolve()
} I expect that You have a point about missing out on the error when you add the semicolon. But if the But YMMV and what you prefer is opinionated. Which is fine for |
Beta Was this translation helpful? Give feedback.
-
Looked around and didn't find any discussion of this anywhere.
It seems to me (as a relative newcomer to Rust) that
semicolon_if_nothing_returned
is a detrimental lint by encouraging newcomers to make style choices that will make things more difficult to refactor later.(I understand that I can turn the lint off, and I do. And I understand that
pedantic
is supposed to be opinionated. I'm just curious what others think about it, why it's worth including, etc.)Let's say I have some code like this:
This kind of code isn't all that surprising. Maybe resolving the request doesn't return any kind of error because whatever backend
Request
is wrapping has no error reporting. Maybe we're blindly twiddling bits on a GPIO pin, or something else like that. Alternatively, it's possible that we're dealing with some framework where an error toRequest::resolve
cannot be meaningfully handled by the caller (so instead we panic/abort/whatever).Clippy complains about our code:
So we listen to clippy and do what it asks. Now, months later whatever underlying framework we're using has changed, and resolving a request gives us some kind of
Token
back:And we've changed nothing else. At some of our call sites, we forgot to pass through the token. The result: slience.
Of course, we could mark our token as
must_use
, but that doesn't always make sense - maybe the token is helpful only occasionally, but should still be plumbed up to higher-level code (i.e. whatever callshandle_request
)If we didn't listen to clippy and skipped the semicolon, instead we'd have:
Ultimately, whether or not you put a semicolon at the end of a function body isn't a matter of just style, as the lint implies. You're deciding whether or not it would make sense for a potential future return value to propagate through through this function or not.
Another situation where this might come up: Non Generic Inner Functions. Clippy complains about the following:
But then if you listen to clippy, then later refactor the code:
You get no warning! If you ignored Clippy, you get:
Of course, in obvious cases like I'm bringing up here the mistake is obvious. But in a complicated code base the mistake won't necessarily be so obvious.
If you follow the link from the warning, you get this under "Why is it bad":
Which is, to say the least, unconvincing. You're trading in a future compiler error that can warn you of bugs you introduced into the codebase, and in exchange you get to make a future git diff one line smaller? I don't think it's worth it.
So hopefully I've made clear why this lint might be harmful, but perhaps it could have some utility.
It would be useful to point out to newcomers that "this is a thing you should be thinking about"! I knew about this footgun before I even started writing Rust because of a YouTube video of "style tips" I watched at some point - I suspect most don't encounter it until it's too late.
The lint in its current form doesn't help. It just blanket-discourages skipping the semicolon, which does nothing towards informing the developer. So maybe instead the lint should act as a little nudge: "You're using semicolons inconsistently - did you know you should be carefully thinking about it?" Then once the developer is aware of this, they can turn off the lint.
Anyway, thoughts appreciated. Thanks
Beta Was this translation helpful? Give feedback.
All reactions