Skip to content

mypy is confused by return values from generators #695

Closed

Description

@gvanrossum

This is fine:

from typing import Iterator

def foo() -> Iterator[int]:
    yield 42

x = next(foo()) + 1000
print(x)

But now try this:

from typing import Iterator

def foo() -> Iterator[int]:
    yield 42
    return 'abc'

This complains about the return statement:

g.py, line 5: Incompatible return value type: expected typing.Iterator[builtins.int], got builtins.str

It's matching the generator return value (which is only accessible by a caller that uses yield from) to the declared return type (which is just the type of what you get by calling foo().

Activity

  1. spkersten commented on May 21, 2015

    @spkersten
    Contributor

    I've been fixing this (see spkersten/generator). Type checking return already works in that branch, only yield from and some special casing for coroutines need a bit more work.

    On 21 mei 2015, at 00:11, Guido van Rossum [email protected] wrote:

    This is fine:

    from typing import Iterator

    def foo() -> Iterator[int]:
    yield 42

    x = next(foo()) + 1000
    print(x)
    But now try this:

    from typing import Iterator

    def foo() -> Iterator[int]:
    yield 42
    return 'abc'
    This complains about the return statement:

    g.py, line 5: Incompatible return value type: expected typing.Iterator[builtins.int], got builtins.str
    It's matching the generator return value (which is only accessible by a caller that uses yield from) to the declared return type (which is just the type of what you get by calling foo().

    —
    Reply to this email directly or view it on GitHub.

  2. gvanrossum commented on Jan 13, 2016

    @gvanrossum
    MemberAuthor

    @spkersten, do you still have that branch? If not I'm probably going to look into this -- there also seems overlap with #642 and #1011.

  3. gvanrossum commented on Jan 14, 2016

    @gvanrossum
    MemberAuthor

    FWIW, I think that the example using return 'abc' should be rejected, but the error message should indicate that a generator declared to return an Iterator should not return a value in a return statement. However, if the function return is declared as -> Generator[X, Y, Z] then the return expression should be type-checked against Z, and the value returned by a yield expression should be type-checked against Y. IOW, ue these mnemonics:

    def foo() -> Generator[X, Y, Z]:
        yield x   # or "yield" if X is None
        y = yield x   # or "y = yield" if X is None (either way only if Y isn't None)
        return z  # or "return" if Z is None
    

    We could treat Iterator[X] as Generator[X, Y, Z] except I still think that even return None should be disallowed -- only return should be allowed if the function declaration doesn't use Generator (because that's the pre-3.3 way).

  4. gvanrossum commented on Jan 15, 2016

    @gvanrossum
    MemberAuthor

    @sakana will address this next. (@jukka: can you add @sakana as a committer? It's David. :-)

  5. ddfisher commented on Jan 15, 2016

    @ddfisher
    Collaborator

    I'm @ddfisher now!

  6. JukkaL commented on Jan 15, 2016

    @JukkaL
    Collaborator

    Added @ddfisher.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugmypy got something wrong

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions