It would be useful to have the option to show an error when a function's non-None returned value is not used. For example in this code:
def greeting(name: str) -> str:
return f"Hi {name}"
def greet(name: str) -> None:
greeting(name)
I would like to get an error on the call to greeting inside of greet because a value is returned but unused. If a returned value is meant to be ignored it would expressed explicitly with _ = greeting(name) or _unused_greeting = greeting(name).
It is so common in Python to ignore return results of a function call that I don't think this check would be practical. Such an error would rarely prevent real bugs in the code.
A large false positive rate plus low value means that this is probably not something we'd implement.
That's understandable in the context of many Python codebases.
I do see value in this check for new code, particularly when using a relatively unfamiliar library, to catch accidental implicit ignores. I see even greater value during refactoring and upgrades to external libraries. A check like this would signal ahead of time if a function has changed its behavior, for example, from raising an exception to returning Optional or some other explicit status value.
Without such a check, that change could easily be missed and failures silently ignored until something breaks in a visible way.
I agree with both of you - It is common to ignore return results, however, information or a warning about the result being ignored could be valuable.
I think it is worth informing the user about the possible misuse of a function.
There's a useful warning which is similar to this: when one forgets to await a coroutine which is used for its side effect only.
import asyncio
async def main():
asyncio.sleep(1)
What about the case where a function returns a union that includes None? Would you consider that return value OK to ignore?
@erictraut I would not consider that ok to ignore because the other union possibilities might be missed. As an example, a union could be the result of a lookup which could return a usable value if one is found or None if no result is available. I wouldn't want to accidentally ignore a useful return value, so in that case I'd expect to use type narrowing (or eventually a match statement) to verify the result.
This will appear in the next release of pyright. It's implemented as a new diagnostic check called "reportUnusedCallResult". It's set to "none" by default, but you can enable it by setting it to "warning" or "error".
I tried enabling it on my team's Python code base (approximately 250K lines of code), and it produced 700+ errors when enabled. I did a quick scan of several dozen of these issues, and none of them appeared to be an actual bug. So I stand by my original assumption that this diagnostic rule will produce a lot of noise with relatively little benefit, but maybe it will occasionally detect a real problem.
This is now implemented in Pyright 1.1.89, which I just published. It will also appear in the next Pylance release.
Thank you @erictraut!
Most helpful comment
There's a useful warning which is similar to this: when one forgets to await a coroutine which is used for its side effect only.