Skip to content

attrs plugin error: "The erased type of self '...*' is not a supertype of its class" on class definition with a generic using a constrained type variable, but then seems to work fine after definition #5542

Closed

Description

@glyph

Consider the following example:

from typing import TypeVar, Generic
import attr

class V:
    pass

class W:
    pass

T = TypeVar("T", V, W)

@attr.s(auto_attribs=True)
class A(Generic[T]):
    v: T

reveal_type(A(W()))

My expectation here would be a revealed type of A[W*], which I do get.

But I also get an error on the @attr.s definition:

The erased type of self 'V*' is not a supertype of its class 'A[T`1]'
The erased type of self 'W*' is not a supertype of its class 'A[T`1]'

if I remove the constraints on T, (i.e. T = TypeVar("T")) then the errors go away.

Activity

  1. gvanrossum commented on Aug 30, 2018

    @gvanrossum
    Member

    Maybe the attrs plugin author (@euresti) can shed some insight?

  2. ilevkivskyi commented on Aug 30, 2018

    @ilevkivskyi
    Member

    This may be related to #5263 (if not a duplicate).

  3. ilevkivskyi commented on Aug 30, 2018

    @ilevkivskyi
    Member

    Just to clarify, both issues may be caused by bad interaction of patched self/cls with checkmember.bind_self().

  4. euresti commented on Aug 31, 2018

    @euresti
    Contributor

    Actually. I can repro with dataclasses too.

    from typing import TypeVar, Generic
    import attr
    from dataclasses import dataclass
    
    class V:
        pass
    
    class W:
        pass
    
    T = TypeVar("T", V, W)
    
    @dataclass(order=True)
    class A(Generic[T]):
        v: T
    
    reveal_type(A(W()))
    

    So it's related to the added __cmp-ish__ methods

  5. ilevkivskyi commented on Aug 31, 2018

    @ilevkivskyi
    Member

    OK, the problem is here and here where we unconditionally grab id=1 for the self-type type variable thus causing a type variable clash (the same probably happens for attrs). I think the solution would be to check somehow the next available id instead.

    Also btw by agreement ids for generic functions/methods should have negative numbers.

  6. euresti commented on Aug 31, 2018

    @euresti
    Contributor

    Would the solution just be to make the id -1? It seems to me like -1 should never be used at this point because negative numbers are used for methods/functions and I'm at this point creating it right? Or are the id's global in scope?

  7. ilevkivskyi commented on Sep 1, 2018

    @ilevkivskyi
    Member

    After some thinking it seems to me just using -1 should be fine since the methods are auto-generated anyway. Btw, I have found that senamal_namedtuple also uses 1 instead of -1. Could you please try replacing it by -1 in both plugins and in named tuple code and play with it trying to break (try some nested classes within generic functions, maybe some scenarios with type inference)?

  8. added a commit that references this issue on Sep 1, 2018
    da8c0e5
  9. added a commit that references this issue on Sep 2, 2018
    f772d45
  10. added a commit that references this issue on Sep 3, 2018
    2c9d11e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions