Skip to content
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

__subclasses__() -> "Only concrete class can be given where "Type[C]" is expected" #6199

Closed
asottile opened this issue Jan 16, 2019 · 7 comments

Comments

@asottile
Copy link
Contributor

this seems related to #5374 but only in the error message (?)

I'm trying to port a section of code that was previously using a metaclass to just using __subclasses__. Here's a minimal example of what I'm trying to do:

import abc
import inspect
from typing import Dict
from typing import List
from typing import Type


class C(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def foo(self):
        raise NotImplementedError(foo.__name__)


def _make_reg() -> Dict[str, Type[C]]:
    ret: Dict[str, Type[C]] = {}

    #subclasses: List[Type[C]] = C.__subclasses__()
    subclasses = C.__subclasses__()
    reveal_type(C.__subclasses__())
    reveal_type(subclasses)
    while subclasses:
        cls = subclasses.pop()
        subclasses.extend(cls.__subclasses__())

        if inspect.isabstract(cls):
            continue

        if cls.__name__ in ret:
            raise AssertionError(cls.__name__, ret[cls.__name__], cls)
        else:
            ret[cls.__name__] = cls

    return ret


REG = _make_reg()

This, as written, fails with:

$ mypy --version
mypy 0.650
$ mypy t.py
t.py:19: error: Revealed type is 'builtins.list[def () -> t.C]'
t.py:20: error: Revealed type is 'builtins.list[def () -> t.C]'
t.py:31: error: Only concrete class can be given where "Type[C]" is expected

If I replace the assignment of subclasses with the commented out line, it succeeds:

$ mypy t.py
t.py:19: error: Revealed type is 'builtins.list[def () -> t.C]'
t.py:20: error: Revealed type is 'builtins.list[Type[t.C]]'
  1. why does the annotation make this allowable?
  2. is the original message a bug? I believe I'm dealing entirely in Type[C] objects in a typesafe manner even without the inspect.isabstract call (notice I'm never even attempting to construct a Type[C])
@ilevkivskyi
Copy link
Member

ilevkivskyi commented Jan 16, 2019

This is a duplicate of #5374 and #4717. You can read the issues for why it may be unsafe (essentially in this case we can't exclude that dict.__setitem__() instantiates cls, but as @JukkaL mentioned in both issues, this looks like an overkill).

@asottile
Copy link
Contributor Author

asottile commented Jan 16, 2019

under what circumstance would dict.__setitem__ cause cls to be instantiated?

this also still doesn't explain why adding an annotation causes it to be ok (which is why I created a separate issue from those two)

@ilevkivskyi
Copy link
Member

under what circumstance would dict.__setitem__ cause cls to be instantiated?

Although in your code ret is just a dict (not a subclass), a subclass of dict can do this.

this also still doesn't explain why adding an annotation causes it to be ok

It does. Because with your annotation cls will be Type[C], and passing Type[C] where Type[C] is expected is OK.

@asottile
Copy link
Contributor Author

isn't the place where I added the annotation also an assignment from () -> C to Type[C]? I would think that would also trigger this error

@ilevkivskyi
Copy link
Member

No, that check was added only as an additional special-case check when the types appear as "top level" in an assignment or function call, it doesn't affect subtyping, so doesn't trigger when the types appear in a nested position.

This whole abstract Type[...] was already a compromise between false positives and false negatives, and from what we see now it is probably a bit too "aggressive".

Also please stop arguing, it is not helpful.

@asottile
Copy link
Contributor Author

I'm not arguing, simply curious -- thanks for the explanation that's all I wanted here <3

@ilevkivskyi
Copy link
Member

@asottile OK, sorry, sometimes it is hard to get the tone from written text :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants