-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Make revealed type of Final vars distinct from non-Final vars #7955
Make revealed type of Final vars distinct from non-Final vars #7955
Conversation
This diff changes how we format Instances with a last known value when displaying them with `reveal_type`. Previously, we would always ignore the `last_known_value` field: ```python x: Final = 3 reveal_type(x) # N: Revealed type is 'builtins.int' ``` Now, we format it like `Literal[3]?`. Note that we use the question mark suffix as a way of distinguishing the type from true Literal types. ```python x: Final = 3 y: Literal[3] = 3 reveal_type(x) # N: Revealed type is 'Literal[3]?' reveal_type(y) # N: Revealed type is 'Literal[3]' ``` While making this change and auditing our tests, I also discovered we were accidentally copying over the `last_known_value` in a few places by accident. For example: ```python from typing_extensions import Final a = [] a.append(1) a.append(2) # Got no error here? reveal_type(a) # Incorrect revealed type: got builtins.list[Literal[1]?] b = [0, None] b.append(1) # Got no error here? reveal_type(b) # Incorrect revealed type: got builtins.list[Union[Literal[0]?, None]] ``` The other code changes I made were largely cosmetic. Similarly, most of the remaining test changes were just due to places where we were doing something like `reveal_type(0)` or `reveal_type(SomeEnum.BLAH)`. This changes should help greatly simplify some of the tests I want to write for python#7169 and also help make a somewhat confusing and implicit part of mypy more visible.
Note: I wasn't 100% sure what the new reveal_type format ought to look like. I was initially thinking of doing things like I'm open to other ideas though. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! We could bikeshed this for a long time, but I think it is not critical, as all the proposed forms are fine and definitely better than the current one, which hides important details.
Go ahead after updating the Python 3.8 tests!
docs/source/literal_types.rst
Outdated
@@ -138,8 +138,27 @@ the above program almost as if it were written like so: | |||
reveal_type(19) | |||
expects_literal(19) | |||
|
|||
This is why ``expects_literal(19)`` type-checks despite the fact that ``reveal_type(c)`` | |||
reports ``int``. | |||
In other words, the type of ``c`` is *context-dependent*: It could be either ``int`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sentence is a bit repetitive, there is almost the same one paragraph above, but it uses term "context-sensitive" instead of "context-dependent". It is better to be more consistent with terms here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried editing this section of the docs more heavily. If you have time, could you give the new version a second sanity check?
return t.copy_modified( | ||
args=[a.accept(self) for a in t.args], | ||
last_known_value=None, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Did you add a test for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point -- I initially didn't since we already had several tests unrelated to literal types that were breaking because of this.
But I think it'd be good to exercise this more directly, so I added a test to check-literals.test
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank for updates! I double-checked the docs, just couple small suggestions there.
docs/source/literal_types.rst
Outdated
when you try using those types in places that are not explicitly expecting a ``Literal[...]``. | ||
For example, compare and contrast what happens when you try appending these types to a list: | ||
|
||
..code-block:: python |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
..code-block:: python | |
.. code-block:: python |
docs/source/literal_types.rst
Outdated
b: Literal[19] = 19 | ||
|
||
# Mypy will chose to infer List[int] instead of List[Literal[19]?] or | ||
# List[Literal[19]] since the former is most likely more useful. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shorten this comment to say just # Mypy will chose to infer List[int] here
This diff changes how we format Instances with a last known value when displaying them with
reveal_type
.Previously, we would always ignore the
last_known_value
field:Now, we format it like
Literal[3]?
. Note that we use the question mark suffix as a way of distinguishing the type from true Literal types.While making this change and auditing our tests, I also discovered we were accidentally copying over the
last_known_value
in a few places by accident. For example:The other code changes I made were largely cosmetic.
Similarly, most of the remaining test changes were just due to places where we were doing something like
reveal_type(0)
orreveal_type(SomeEnum.BLAH)
.The main motivation behind this diff is that once this lands, it should become much simpler for me to write some tests I'll need while revamping #7169. It also helps make a somewhat confusing and implicit part of mypy internals more visible.