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. |
JukkaL
left a comment
There was a problem hiding this comment.
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.
Test also joins with unions containing literals types.
There was a problem hiding this comment.
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.
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.
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.
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.
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! |
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_typemethod in theconstraints.ConstraintBuilderVisitorandjoin.TypeJoinVisitormethods. 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).