Skip to content

Mypy appears to infer the correct type, but throws an error. #8517

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

Closed
ninjaaron opened this issue Mar 9, 2020 · 3 comments
Closed

Mypy appears to infer the correct type, but throws an error. #8517

ninjaaron opened this issue Mar 9, 2020 · 3 comments
Labels
topic-descriptors Properties, class vs. instance attributes topic-runtime-semantics mypy doesn't model runtime semantics correctly

Comments

@ninjaaron
Copy link

ninjaaron commented Mar 9, 2020

Thanks so much for Mypy! It's a very useful tool.

I was messing around to see if I could write a generic iterator type in Python that would be faster than a generator function. (needless to say, I did not succeed). However, I got a rather unusual message from mypy:

otheriter.py:28: error: Incompatible return value type (got "V", expected "V")
Found 1 error in 1 file (checked 1 source file)

So, it expected the thing it got and then showed an error anyway.

Code is here:

from typing import TypeVar, Generic, Callable, Tuple, Optional

S = TypeVar("S")
V = TypeVar("V")


class Sequence:
    __slots__ = "state", "f"

    def __init__(self, state: S):
        """

        """
        self.state = state

    def __call__(self, func: Callable[[S], Optional[Tuple[V, S]]]):
        self.f = func
        return self

    def __iter__(self):
        return type(self)(self.state)(self.f)

    def __next__(self) -> V:
        out = self.f(self.state)
        if out is None:
            raise StopIteration
        val, self.state = out
        return val


@Sequence((0, 1))
def fibs(state: Tuple[int, int]) -> Optional[Tuple[int, Tuple[int, int]]]:
    a, b = state
    if a > 1_000_000_000:
        return None
    return a, (b, a+b)

When I add generic parameters to the class, I get a different error.

defining the class this way:

class Sequence(Generic[S, V]):
    ...

produces this error:

otheriter.py:31: error: Argument 1 to "__call__" of "Sequence" has incompatible type "Callable[[Tuple[int, int]], Optional[Tuple[int, Tuple[int, int]]]]"; expected "Callable[[Tuple[int, int]], Optional[Tuple[<nothing>, Tuple[int, int]]]]"
Found 1 error in 1 file (checked 1 source file)

It says it expected <nothing> in there. I don't know what that is.

Sorry if this is a duplicate.

@ninjaaron
Copy link
Author

I got it to check with this class definition:

class Sequence(Generic[S, V]):
    __slots__ = "state", "f"

    f: Callable[[S, S], Optional[Tuple[V, S]]]

    def __init__(self, state: S):
        """

        """
        self.state = state

    def __call__(self, func):
        self.f = func
        return self

    def __iter__(self):
        return type(self)(self.state)(self.f)

    def __next__(self) -> V:
        out = self.f(self.state)
        if out is None:
            raise StopIteration
        val, self.state = out
        return val

This doesn't look entirely correct to me. Mypy is treating f like a bound method, rather than an instance variable i.e. wants f it to take two input parameters--the first presumably being self. It doesn't check if only one input parameter is given.

@msullivan
Copy link
Collaborator

Hm. Mypy doesn't have a clear distinction internally between instance and class variables, and that is probably causing trouble here

@AlexWaygood AlexWaygood added topic-runtime-semantics mypy doesn't model runtime semantics correctly topic-descriptors Properties, class vs. instance attributes labels Mar 28, 2022
@AlexWaygood
Copy link
Member

The first example I would expect to fail, as the type variable V is unbound. I'm not sure what's going on in the second example, but the bug in the third example is tracked here: #6910

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic-descriptors Properties, class vs. instance attributes topic-runtime-semantics mypy doesn't model runtime semantics correctly
Projects
None yet
Development

No branches or pull requests

3 participants