-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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 literal exprs have inferred type of 'Literal' based on context #5990
Make literal exprs have inferred type of 'Literal' based on context #5990
Conversation
This pull request modifies the type checking logic so that literal expressions will have an inferred type of 'Literal' if the context asks for a literal type. This pull requests also implements the `visit_literal_type` method in the `constraints.ConstraintBuilderVisitor` and `join.TypeJoinVisitor` methods. Both visitors are exercised indirectly through the "let's use literal types in collection contexts" code, but only the latter is tested directly: I wasn't really sure how to directly test `ConstraintBuilderVisitor`. The implementation is simple though -- I'm pretty sure literal types count as a "leaf type" so it's fine to return an empty list (no constraints).
Note to self: add tests here making sure inference works as expected with overloads. I guess maybe with generics as well, while we're at it? Or maybe in a follow-up diff specifically about generics. |
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.
Great, this will make literal types useful for some real use cases! Left mostly ideas about additional test cases.
mypy/test/testtypes.py
Outdated
self.assert_simple_join(lit1, lit2, a) | ||
self.assert_simple_join(lit1, lit3, self.fx.o) | ||
self.assert_simple_join(lit1, self.fx.anyt, self.fx.anyt) | ||
self.assert_simple_join(self.fx.anyt, lit1, self.fx.anyt) |
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.
Test also joins with unions containing literals types.
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.
Done. I also didn't see until now that assert_join
internally already tests symmetry and calls assert_simple_join
, so I went ahead and removed some existing duplicate tests.
reveal_type(f2) # E: Revealed type is 'def (x: Literal[' foo bar ']) -> Literal[' foo bar ']' | ||
reveal_type(f3) # E: Revealed type is 'def (x: Literal[' foo bar ']) -> Literal[' foo bar ']' | ||
reveal_type(f4) # E: Revealed type is 'def (x: Literal['foo']) -> Literal['foo']' | ||
reveal_type(f5) # E: Revealed type is 'def (x: Literal['foo']) -> Literal['foo']' |
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.
Test calls to a function accepting a union of string literal types. Call it with each supported literal and also union argument types.
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.
Added to a test named 'testLiteralCallingUnionFunction'.
y: Literal['a', 'b'] | ||
f(x, y) # E: Argument 1 to "f" has incompatible type "Union[Literal['a'], Literal['b']]"; expected "Literal['a']" \ | ||
# E: Argument 2 to "f" has incompatible type "Union[Literal['a'], Literal['b']]"; expected "Literal['a']" \ | ||
[out] |
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.
Test overload where there are no literal types and one of the overload items is T
-> T
. This shouldn't produce literal types when called with a literal argument.
Test overload where one item accepts a literal 'x'
and another takes T
-> T
. When called with an unrelated literal 'y'
, will this produce a literal type or a non-literal type?
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 attempted adding a test case named "testLiteralInferredInOverloadContextWithTypevars" that exercises these. Let me know if those tests match what you had in mind.
@JukkaL -- this should be ready for a second look whenever! |
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.
Looks good now!
This pull request modifies the type checking logic so that literal expressions will have an inferred type of 'Literal' if the context asks for a literal type. That is, it implements support for this:
This pull requests also implements the
visit_literal_type
method in theconstraints.ConstraintBuilderVisitor
andjoin.TypeJoinVisitor
methods. Both visitors are exercised indirectly through the "let's use literal types in collection contexts" code, but only the latter is tested directly: I wasn't really sure how to directly testConstraintBuilderVisitor
.The implementation is simple though -- I'm pretty sure literal types count as a "leaf type" so it's fine to return an empty list (no constraints).