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

Adding # type: ignore to EnumClass[string_value] doesn't set the type to Any #2416

Closed
gvanrossum opened this issue Nov 7, 2016 · 2 comments · Fixed by #2419
Closed

Adding # type: ignore to EnumClass[string_value] doesn't set the type to Any #2416

gvanrossum opened this issue Nov 7, 2016 · 2 comments · Fixed by #2419
Labels
bug mypy got something wrong

Comments

@gvanrossum
Copy link
Member

gvanrossum commented Nov 7, 2016

Example:

from typing import Dict
from enum import Enum
class E(Enum):
    V = 'V'
d = {}  # type: Dict[E, int]
def f(s: str):
    e = E[s]  # type: ignore
    d[e] = 0  # Still error here

We have to use # type: ignore on the line e = E[s] because of #741. But somehow the type of e, when ignoring the error, is not Any but something else. So on the last line we get

__tmp__.py: note: In function "f":
__tmp__.py:8: error: Invalid index type "E" for "dict"

The weird thing is that if e had type E, d[e] would be valid, so the error is also somehow lying...

UPDATE: When trying to repro this, don't try E['V'] -- mypy sees the literal and gives some other error, probably also because of #741.

@gvanrossum
Copy link
Member Author

This was introduced by 57ff82b (PR #2378, Implement generic type aliases). @ilevkivskyi Can you look into this? It would break our internal build (if we were to update mypy).

@ilevkivskyi
Copy link
Member

@gvanrossum
The strange error is because message simply takes the name of type. Here actual type of e is def (value: Any) -> __tmp__.E (type object), not __tmp__.E (instance), and the former is indeed an invalid type for index where the latter is expected.

The problem itself appear because ignored line is interpreted by mypy as e = E. This is because TypeAnalyserPass3 tries to recover incorrect instances instead of simply returning Any.

This is a common behaviour. For example:

def g() -> Dict[int]: # type: ignore
    ...
reveal_type(g())  # Revealed type is Dict[Any, Any]

My recent PR just brought this behaviour also to aliases (before aliases always returned Any), and e = E[s] looks like a type alias.

I think the right way to fix this is to mark such "recovered" instances as invalid, so that they could be turned into Any in checker. I do this for type aliases in PR #2419

The mentioned PR fixes the problem, but I am thinking maybe we should reconsider recovery after errors (PEP 484 seems to be silent about this): should errors always lead to Any, or to best possible inferred type? Or first option for # type: ignore and the second by default? Although probably it is not a good idea to make such changes few days before release.

gvanrossum pushed a commit that referenced this issue Nov 8, 2016
Fixes #2416.

This is a minimalistic fix (basically just restoring status quo for invalid aliases).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants