Skip to content
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

Generic type is not inferred across descriptor class methods #8516

Closed
sjustas opened this issue Mar 9, 2020 · 5 comments
Closed

Generic type is not inferred across descriptor class methods #8516

sjustas opened this issue Mar 9, 2020 · 5 comments
Labels
crash priority-0-high topic-descriptors Properties, class vs. instance attributes

Comments

@sjustas
Copy link

sjustas commented Mar 9, 2020

Tried to write type stubs for lazy package. Lazy provides a descriptor that invokes the underlying method only once and caches the result in the instance.

The inferred type is <nothing>, so mypy crashes when checking expressions.

from typing import Any, Generic, Callable, TypeVar

T = TypeVar('T')

class lazy:
    def __init__(self, func: Callable[[Any], T]) -> None: ...
    def __get__(self, inst: Any, inst_cls: Any) -> T: ...

class Haystack:
    @lazy
    def hasNeedles(self) -> bool:
        # some expensive lookup we want to execute only once
        return True

reveal_type(Haystack().hasNeedles)

# checking this expression crashes
x = Haystack().hasNeedles or True
<...>
note: Revealed type is '<nothing>'
<...>
version: 0.761
Traceback (most recent call last):
  File "mypy/checkexpr.py", line 3645, in accept
  File "mypy/nodes.py", line 1736, in accept
  File "mypy/checkexpr.py", line 2029, in visit_op_expr
  File "mypy/checkexpr.py", line 2662, in check_boolean_op

If lazy was defined as a function, type gets inferred correctly.

def lazy(func: Callable[[Any], T]) -> T: ...
note: Revealed type is 'builtins.bool*'
@sjustas
Copy link
Author

sjustas commented Mar 9, 2020

Issues that might be related: #5738, #1317

@janverb
Copy link
Contributor

janverb commented Mar 9, 2020

This works as expected if you change lazy to inherit from Generic[T]. Crashing seems like the wrong response though.

@emmatyping
Copy link
Collaborator

emmatyping commented Mar 9, 2020

We definitely should not crash. It might be nice if we have an unused type variable in a method to note the class may need to inherit from Generic.

@sjustas
Copy link
Author

sjustas commented Mar 10, 2020

Thanks for such a quick response. You guys rock!
Yeah, a warning that class needs to be generic would've been useful.

@AlexWaygood AlexWaygood added the topic-descriptors Properties, class vs. instance attributes label Mar 26, 2022
@JukkaL
Copy link
Collaborator

JukkaL commented Aug 24, 2022

This doesn't crash any more on master. Here's the output I get:

$ mypy t/t3.py
t/t3.py:7: error: A function returning TypeVar should receive at least one argument containing the same Typevar
t/t3.py:15: note: Revealed type is "<nothing>"
t/t3.py:18: error: Need type annotation for "x"
Found 2 errors in 1 file (checked 1 source file)

@JukkaL JukkaL closed this as completed Aug 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crash priority-0-high topic-descriptors Properties, class vs. instance attributes
Projects
None yet
Development

No branches or pull requests

5 participants