Skip to content

Assignment to next in class body of Iterator elicits error (in PY2 mode) #2503

Closed

Description

@gvanrossum

Since #2380 was merged, the following example elicits an error when type-checked in Python 2 mode:

from typing import Iterator
class A: pass
class X(Iterator[A]):
  def __next__(self):
    # type: () -> A
    pass
  next = __next__

The error comes from the code added by #2380:

__tmp__.py: note: In class "X":
__tmp__.py:7: error: Incompatible types in assignment (expression has type Callable[[X], A], variable has type Callable[[Iterator[A]], A])

Activity

  1. JukkaL commented on Nov 28, 2016

    @JukkaL
    Collaborator

    The type of next in the class body should likely be inferred as Callable[[X], A] (i.e., the type of self should be derived from the enclosing class).

  2. gvanrossum commented on Nov 28, 2016

    @gvanrossum
    MemberAuthor
  3. TrueBrain commented on Nov 29, 2016

    @TrueBrain
    Contributor

    Just to check if I understand the problem correctly, the following should also pass mypy not? (but it doesn't before the revert; same error as above)

    T = TypeVar("T")
    
    class B(Generic[T]):
            v = None  # type: T
            def n(self):
                    # type: () -> T
                    return self.v
    
    class C(B[int]):
            def m(self):
                    # type: () -> int
                    return 1
            n = m
    
  4. gvanrossum commented on Nov 29, 2016

    @gvanrossum
    MemberAuthor
  5. TrueBrain commented on Nov 29, 2016

    @TrueBrain
    Contributor

    Found an even more elegant example:

    class B():
            def n(self, a: int) -> None: pass
    class C(B):
            def m(self, a: int) -> None: pass
            n = m
    

    Pushed a fix, but I would love some feedback if this is an okay way to go.

    Additionally, would you be able to check if with this version your repo does validate successfully?

  6. gvanrossum commented on Nov 30, 2016

    @gvanrossum
    MemberAuthor

    Yes, that example is better because it shows the problem is not due to generics.

    Where's your fix? You're going to have to create a new PR.

  7. JukkaL commented on Nov 30, 2016

    @JukkaL
    Collaborator

    Both examples look good.

  8. gvanrossum commented on Dec 5, 2016

    @gvanrossum
    MemberAuthor

    However here's a more complex example:

    class I:
        def foo(self) -> None: pass
    
    class A(I):
        def foo(self) -> None: pass
    
    class B(A):
        def bar(self) -> None: pass
        foo = bar
    
    class C(B):
        def bar(self) -> None: pass
        foo = bar
  9. JukkaL commented on Jan 16, 2017

    @JukkaL
    Collaborator

    Note that this becomes relevant after #2510 is merged.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions