Repository navigation
Literal types tracking issue #5935
Copy link
Copy link
Closed
Labels
Description
This issue tracks TODOs for literal types.
Core work
- Modify the parser so it can handle literal expressions in types (Add basic end-to-end support for Literal types #5947)
- Make any necessary changes to semantic analysis (see below) (Add basic end-to-end support for Literal types #5947)
- Implement the core type-checking logic (also see below)
- Implement logic for determining when and when not to infer Literal (Make literal exprs have inferred type of 'Literal' based on context #5990)
- Validate that everything works in incremental mode and with the mypy daemon (Add tests for Literal types with incremental and fine-grained mode #6075)
- Add "extra" features (again see below)
- Write docs
Parsing/semantic analysis follow-up tasks
- Distinguish between byte strings, native strings, and unicode in Python 2 and Python 3 (Add support for byte and unicode Literal strings #6087)
- Make sure everything still works with
from __future__ import unicode_literals(Add support for byte and unicode Literal strings #6087) - Add more tests for forward references and related shenanigans
- Add logic to make sure literal expressions are coerced to the correct type based on context (Make literal exprs have inferred type of 'Literal' based on context #5990)
Error messages
- Add better error messages for complex numbers (Improve error messages related to literal types #6149)
- Add better error messages for weird expressions in general (e.g. disallowing
Literal[1 + 2]. This will probably involve moving all invalid type checking into the semantic analysis layer? (Improve error messages related to literal types #6149) - Resolve Regression: error messages for literal expressions in invalid places are worse #5989 (Improve error messages related to literal types #6149)
Implementing and testing type visitors
Implement and write tests that exercise the following visitors. (Introduced by #5934)
- constraints.ConstraintBuilderVisitor (Make literal exprs have inferred type of 'Literal' based on context #5990)
- join.TypeJoinVisitor (Make literal exprs have inferred type of 'Literal' based on context #5990)
- meet.TypeMeetVisitor (Implement meet for literal types; add tests for 'is_same_type' #6043)
- subtypes.ProperSubtypeVisitor (Add basic end-to-end support for Literal types #5947)
- subtypes.SubtypeVisitor (Add basic end-to-end support for Literal types #5947)
- typeanal.TypeAnalyzer (Add basic end-to-end support for Literal types #5947)
- typeanal.TypeAnalyzerPass3 (Add basic end-to-end support for Literal types #5947)
- types.TypeStrVisitor (Add basic end-to-end support for Literal types #5947)
- type_visitor.TypeVisitor (indirectly, by other tests)
- type_visitor.TypeTranslator (indirectly, by other tests)
The following have preliminary implementations, but are missing associated tests:
- erasetype.EraseTypeVisitor (indirectly, by Add tests for literals and generics #6035)
- expandtype.ExpandTypeVisitor (indirectly, by Add tests for literals and generics #6035)
- fixup.TypeFixer (important for Enums)
- sametypes.SameTypeVisitor (Implement meet for literal types; add tests for 'is_same_type' #6043)
- server.astdiff.SnapshotTypeVisitor (Add tests for Literal types with incremental and fine-grained mode #6075)
- server.deps.TypeTriggersVisitor (Add tests for Literal types with incremental and fine-grained mode #6075)
Other checks to add in the type-checking layer
- Make sure we cannot subclass Literals (Prohibit some illegal uses of Literal #6034)
- Blacklist constructs like
Type[Literal[4]]- Actually, should we? Maybe we should treat
Type[Literal[4]]asintinstead -- this might make certain TypeVar shenanigans more smooth. Need to discuss. - Actually, the above idea seems like a bad idea: if we do
x: Literal[3], doingtype(x)ought to return a value with typeType[int], not justint.
- Actually, should we? Maybe we should treat
- Blacklist using
Literal[...]inisinstanceandissubclasschecks (Prohibit some illegal uses of Literal #6034) - Validate
Literalworks as expected when used in generics (Add tests for literals and generics #6035) - Consider having mypy warn if somebody tries doing literally
TypeVar('T', bound=Literal[4])? Need to discuss first.
"Extra" features to add
- Intelligent indexing of tuples, NamedTuples, TypedDict, getattr, and setattr (Add intelligent indexing of tuples, NamedTuples, and TypedDict #6124)
- While I'm at it, design a more intelligent "macro replace" system and try and fix the misc errors we get when using
--disallow-any-expr?
- While I'm at it, design a more intelligent "macro replace" system and try and fix the misc errors we get when using
- Type narrowing with equality and inequality checks
- Interactions with
Final(Add interactions between Literal and Final #6081) - Add custom type guards (see Ivan's comment below, also type refinement in function call #5206)
- Treat bool as a union of
Literal[True]andLiteral[False](see Treat bool as equivalent to Literal[True, False] to allow better type inference #6113)
Things to do before mypy 0.660 is released if literal types aren't going to make it
- Address Regression: error messages for literal expressions in invalid places are worse #5989 -- restore old error messages, and expunge any reference to literal types in any error messages we added. (Remove RawLiteralType synthetic type #6121)
Other things
- Try replacing one of the functions we currently manage using plugins with literal types instead, and see what happens.
- I tried replacing the "open(...)" plugin and re-ran mypy on one of our smaller internal codebases. Out of approximately 680 calls to
open, about 610 of them had 2 or more arguments. We inferred the correct type for about 560 of those. About another 20 of these were passing in string variable arguments as the mode. The remaining 30 require a little more investigation -- some people were passing in**kwargsor**argsin as the argument, etc...
- I tried replacing the "open(...)" plugin and re-ran mypy on one of our smaller internal codebases. Out of approximately 680 calls to
Things that have been deferred to after this project is completed
- Adding support for enums in literal types (and while I'm at it, I might as well investigate overhauling enums in general). Related tasks:
- Treat enum classes as roughly a union of their values
- Better error messages for bad imports (e.g. enums with a coerced type of 'Any')
- In error messages, we seem to quote types using either single quotes or double quotes. This can sometimes lead to messy-looking error messages (e.g.
Revealed type is 'Literal['foo']'). We should standardize on a specific quoting scheme + avoid this weird "nesting" issue. - Make sure we report an error when somebody tries doing
Literal[3]()(andFinal[int]()andProtocol[blah]()...)
Reactions are currently unavailable
Activity
JukkaL commentedon Nov 22, 2018
The plan looks great! I'm looking forward to being able to use literal types.
Add LiteralType and stub methods to type visitors (#5934)
ilevkivskyi commentedon Dec 22, 2018
I think this idea already appeared somewhere, but I think it makes sense to add this to this list: custom type-guards (like in TypeScript):
essentially we just nee to teach binder how to interact with literals.
ilevkivskyi commentedon Jun 14, 2019
@Michael0x2a I propose to use #5206 to track the type-guards idea (literals + binder).
emmatyping commentedon May 19, 2022
There seem to be 3 relatively simple tasks left:
Type[Literal[4]]TypeVar('T', bound=Literal[4])the last two in particular should be good first issues if I'm not mistaken.
hauntsaninja commentedon Nov 12, 2023
I don't know that we need to error for the second one, and I feel we shouldn't disallow erroring for the third one (or any bound to a final type). I can't see what specific tests we'd want to add for the first one.