Skip to content

Generic Self classmethod fails for generic types #3631

Closed

Description

@rowillia

Repro:

from typing import Generic, TypeVar, Type

_T = TypeVar('_T')
SelfType = TypeVar('SelfType', bound='Friend')

class Friend(Generic[_T]):
    @classmethod
    def make(cls: Type[SelfType]) -> SelfType:  # E: Unsupported type Type["SelfType"]
        return cls()

I suspect the issue is that the type should be:

def make(cls: Type[SelfType[T]]) -> SelfType[T]:
        return cls()

But there is no way to express that that I can tell.

Using an instance method behaves as expected:

from typing import Generic, TypeVar, Type

_T = TypeVar('_T')
SelfType = TypeVar('SelfType', bound='Friend')

class Friend(Generic[_T]):
    other = None  # type: Friend

    def make(self: SelfType) -> SelfType:
        return self

Activity

  1. ilevkivskyi commented on Jun 29, 2017

    @ilevkivskyi
    Member

    I think this is a duplicate of #3363 and #2354
    I think we could leave only one of these three issues open and raise its priority.

  2. rowillia commented on Jun 29, 2017

    @rowillia
    ContributorAuthor

    @ilevkivskyi I'm fine with that. AFAICT #2354 is effectively fixed, the code example below works great:

    from typing import Generic, TypeVar, Type
    
    _T = TypeVar('_T')
    SelfType = TypeVar('SelfType', bound='Friend')
    
    class Friend(Generic[_T]):
        other = None  # type: Friend
    
        def make(self: SelfType) -> SelfType:
            return self
    
    class SuperFriend(Generic[_T], Friend[_T]):
        pass
    
    
    reveal_type(SuperFriend[int]().make())  # E: Revealed type is 'test_generic_self.SuperFriend[builtins.int]'

    I'd be fine if classmethods had the same behavior. In fact, @elazarg 's change #3633 mostly fixes this issue. The types (as opposed to <nothing>) are correct but declaring the function make still throws an error:

    from typing import Generic, TypeVar, Type
    
    _T = TypeVar('_T')
    SelfType = TypeVar('SelfType', bound='Friend')
    
    class Friend(Generic[_T]):
        other = None  # type: Friend
    
        @classmethod
        def make(cls: Type[SelfType]) -> SelfType:  # E: Unsupported type Type["SelfType"]
            return cls()
    
    class SuperFriend(Generic[_T], Friend[_T]):
        pass
    
    
    reveal_type(SuperFriend[int]().make())  # E:  Revealed type is 'test_generic_self.SuperFriend*[builtins.int*]'
  3. elazarg commented on Jun 30, 2017

    @elazarg
    Contributor

    I think the Unsupported type Type["SelfType"] error is a separate issue. It happens even for staticmethod, for which there's no specific check for selftype.

  4. rowillia commented on Jun 30, 2017

    @rowillia
    ContributorAuthor

    @elazarg got it. If you can land #2354 I can debug the Type["SelfType"] issue.

  5. gvanrossum commented on Jun 30, 2017

    @gvanrossum
    Member
  6. bharel commented on Jun 29, 2018

    @bharel

    I've been sent here by stackoverflow. Issue is still relevant.

  7. added a commit that references this issue on Aug 2, 2018
    573be3e
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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions