Pyright: Optional error on unused returned value when returned value is not None

Created on 27 Oct 2020  路  9Comments  路  Source: microsoft/pyright

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).

addressed in next version enhancement request

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.

import asyncio

async def main():
    asyncio.sleep(1)

All 9 comments

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!

Was this page helpful?
0 / 5 - 0 ratings