pylance-release icon indicating copy to clipboard operation
pylance-release copied to clipboard

Object of type "None" cannot be called

Open daudef opened this issue 3 years ago • 7 comments

Environment data

  • Language Server version: 2022.5.3 (pyright 73c82fab)
  • OS and version: macOS Monterey 12.4
  • Python version (& distribution if applicable, e.g. Anaconda): 3.10.2 64-bit

Code Snippet

0:  from typing import Callable
1: 
2:  def bug_showcase(cb: Callable[[], int] | None):
3:     l: list[int] = []
4:     for _ in range(0):
5:         if cb is not None:
6:             l += [cb()]
7:         l.append(0)

Repro Steps

  1. Open the file in VSCode.
  2. Pylance (strict mode) underlines the cb identifier (line 6) in red.
  3. It is a bit random, I sometime need to add and remove spaces 3 or 4 times, to update Pylance so it shows the error.

Expected behavior

I'm calling an optional callable after checking that it is not None so there should not be any problem. When hovering the cb identifier (line 6) it should show :

(parameter) cb: () -> int

Actual behavior

When hovering the cb identifier (line 6) it shows :

(parameter) cb: () -> int
Object of type "None" cannot be called   Pylance(reportOptionalCall)
View Problem   No quick fixes available

Pylance infers the correct type for cb but still detects an error. I tried to make the smallest example possible, for example commenting line 7, fixes the issue.

daudef avatar May 31 '22 09:05 daudef

Thanks for the bug report. I'm 95% sure that the underlying cause of this bug has been fixed in the past few days. I'm not entirely sure because I'm finding it difficult to repro the problem. I did get it to happen a few times with the last-published version of Pylance, but I can't get it to occur with the latest build.

The symptom would be explained by the bug fix I introduced for this issue. The code in your sample is also very similar to the code in that bug report.

I'm going to mark the bug as "fixed in next release". If it still occurs for you after the next release of Pylance, we can re-open it, and I'll take another look.

erictraut avatar May 31 '22 15:05 erictraut

This issue has been fixed in version 2022.6.0, which we've just released. You can find the changelog here: CHANGELOG.md

bschnurr avatar Jun 01 '22 23:06 bschnurr

I can confirm that the new version fixed the issue, thank you for your help.

daudef avatar Jun 02 '22 05:06 daudef

I just updated Pylance to v2022.6.10 and the bug (fixed with v2022.6.0) is occurring again.

daudef avatar Jun 13 '22 09:06 daudef

@daudef, I can't think of anything that changed between 2022.6.0 and 2022.6.10 that would have caused a regression. I suspect this is still a lingering bug. Reopening for further investigation.

I'm finding this very hard to repro. I saw it happen once with 2022.6.10, but it goes away almost immediately. I suspect it's a case where evaluation ordering is producing the wrong result.

Here's the code sample without the line numbers:

from typing import Callable

def bug_showcase(cb: Callable[[], int] | None):
    l: list[int] = []
    for _ in range(0):
        if cb is not None:
            l += [cb()]
        l.append(0)

erictraut avatar Jun 13 '22 15:06 erictraut

I've created a tracking bug in the pyright repo.

erictraut avatar Jun 13 '22 15:06 erictraut

I'm no longer able to repro this problem, but I struggled to repro it previously, so I don't know if it's gone.

I'm going to close the tracking bug for now. If you are able to repro it, I'll reopen and investigate further.

erictraut avatar Jul 09 '22 06:07 erictraut

Not sure if this issue fits this thread:

CleanShot 2022-10-25 at 20 28 44

But I get this error when I apply a hook from Wagtail. The actual code snippet:

from wagtail.core import hooks

# Remove entries from pages side menu
@hooks.register("construct_main_menu")
def hide_user_menu_item(request, menu_items):
    menu_items[:] = [item for item in menu_items if item.name != "explorer"]

and the register typings:

def register(hook_name, fn=None, order=0):
     ...

konsalex avatar Oct 25 '22 18:10 konsalex

The bug reported in this issue has been fixed. I think it's safe to mark this as closed.

erictraut avatar Jan 24 '23 21:01 erictraut

Pylance v2023.8.10 Type checking: simple

I got this reportOptionalCall error when I call Callable|None directly from a class instance (database_views[self.table_name]) image

But when I assign this Callable to a local variable, it works fine. image

TimurRin avatar Aug 04 '23 06:08 TimurRin

@TimurRin, this is expected. The type of an expression is not narrowed when using an index expression if the subscript to the index is a dynamic expression like self.table_name. A static type checker cannot guarantee that the type of the index express will remain consistent. If you assign the result of the index expression to a local variable like proc, the value is guaranteed not to change between the assignment and its usage. For more details about type narrowing, refer to this documentation.

erictraut avatar Aug 04 '23 13:08 erictraut