Skip to content

Commit b099496

Browse files
authored
Add LiteralType and stub methods to type visitors (#5934)
This diff adds a 'LiteralType' class to types.py and adds a corresponding stub method to all of the type visitors. Most of these stub methods just throw a 'NotImplementedError', though I did pencil in a few implementations that looked obvious. The reason I'm doing this now instead of later is because I want to start by getting these kind of big, gross, multi-file changes out of the way early and try and have any subsequent pull requests be more focused. I also want to formally confirm that the correct approach here *is* to create a new 'LiteralType' class before I start on the rest of the implementation work. (Other possible approaches would be to tack on some extra attribute to 'Instance', or make 'LiteralType' a subclass of 'Instance'.) No tests, sorry. My plan is to work on modifying the parsing and semantic analysis steps next before returning back to these the unimplemented methods and add tests then -- here's the tracking issue for these TODOs: #5935 Tests shouldn't be necessary, in any case: everything I added just now is basically dead code.
1 parent 1428513 commit b099496

15 files changed

+153
-14
lines changed

mypy/constraints.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from mypy.types import (
66
CallableType, Type, TypeVisitor, UnboundType, AnyType, NoneTyp, TypeVarType, Instance,
77
TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType,
8-
UninhabitedType, TypeType, TypeVarId, TypeQuery, is_named_instance, TypeOfAny
8+
UninhabitedType, TypeType, TypeVarId, TypeQuery, is_named_instance, TypeOfAny, LiteralType,
99
)
1010
from mypy.maptype import map_instance_to_supertype
1111
from mypy import nodes
@@ -473,6 +473,9 @@ def visit_typeddict_type(self, template: TypedDictType) -> List[Constraint]:
473473
else:
474474
return []
475475

476+
def visit_literal_type(self, template: LiteralType) -> List[Constraint]:
477+
raise NotImplementedError()
478+
476479
def visit_union_type(self, template: UnionType) -> List[Constraint]:
477480
assert False, ("Unexpected UnionType in ConstraintBuilderVisitor"
478481
" (should have been handled in infer_constraints)")

mypy/erasetype.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from mypy.types import (
44
Type, TypeVisitor, UnboundType, AnyType, NoneTyp, TypeVarId, Instance, TypeVarType,
55
CallableType, TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType,
6-
DeletedType, TypeTranslator, UninhabitedType, TypeType, TypeOfAny
6+
DeletedType, TypeTranslator, UninhabitedType, TypeType, TypeOfAny, LiteralType,
77
)
88
from mypy.nodes import ARG_STAR, ARG_STAR2
99

@@ -78,6 +78,12 @@ def visit_tuple_type(self, t: TupleType) -> Type:
7878
def visit_typeddict_type(self, t: TypedDictType) -> Type:
7979
return t.fallback.accept(self)
8080

81+
def visit_literal_type(self, t: LiteralType) -> Type:
82+
# The fallback for literal types should always be either
83+
# something like int or str, or an enum class -- types that
84+
# don't contain any TypeVars. So there's no need to visit it.
85+
return t
86+
8187
def visit_union_type(self, t: UnionType) -> Type:
8288
erased_items = [erase_type(item) for item in t.items]
8389
return UnionType.make_simplified_union(erased_items)

mypy/expandtype.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
Type, Instance, CallableType, TypeVisitor, UnboundType, AnyType,
55
NoneTyp, TypeVarType, Overloaded, TupleType, TypedDictType, UnionType,
66
ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, TypeVarId,
7-
FunctionLike, TypeVarDef
7+
FunctionLike, TypeVarDef, LiteralType,
88
)
99

1010

@@ -111,6 +111,10 @@ def visit_tuple_type(self, t: TupleType) -> Type:
111111
def visit_typeddict_type(self, t: TypedDictType) -> Type:
112112
return t.copy_modified(item_types=self.expand_types(t.items.values()))
113113

114+
def visit_literal_type(self, t: LiteralType) -> Type:
115+
# TODO: Verify this implementation is correct
116+
return t
117+
114118
def visit_union_type(self, t: UnionType) -> Type:
115119
# After substituting for type variables in t.items,
116120
# some of the resulting types might be subtypes of others.

mypy/fixup.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
)
1010
from mypy.types import (
1111
CallableType, Instance, Overloaded, TupleType, TypedDictType,
12-
TypeVarType, UnboundType, UnionType, TypeVisitor,
12+
TypeVarType, UnboundType, UnionType, TypeVisitor, LiteralType,
1313
TypeType, NOT_READY
1414
)
1515
from mypy.visitor import NodeVisitor
@@ -206,6 +206,9 @@ def visit_typeddict_type(self, tdt: TypedDictType) -> None:
206206
if tdt.fallback is not None:
207207
tdt.fallback.accept(self)
208208

209+
def visit_literal_type(self, lt: LiteralType) -> None:
210+
lt.fallback.accept(self)
211+
209212
def visit_type_var(self, tvt: TypeVarType) -> None:
210213
if tvt.values:
211214
for vt in tvt.values:

mypy/indirection.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ def visit_tuple_type(self, t: types.TupleType) -> Set[str]:
9090
def visit_typeddict_type(self, t: types.TypedDictType) -> Set[str]:
9191
return self._visit(t.items.values()) | self._visit(t.fallback)
9292

93+
def visit_literal_type(self, t: types.LiteralType) -> Set[str]:
94+
return self._visit(t.fallback)
95+
9396
def visit_star_type(self, t: types.StarType) -> Set[str]:
9497
return set()
9598

mypy/join.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
from mypy.types import (
77
Type, AnyType, NoneTyp, TypeVisitor, Instance, UnboundType, TypeVarType, CallableType,
8-
TupleType, TypedDictType, ErasedType, UnionType, FunctionLike, Overloaded,
9-
PartialType, DeletedType, UninhabitedType, TypeType, true_or_false, TypeOfAny
8+
TupleType, TypedDictType, ErasedType, UnionType, FunctionLike, Overloaded, LiteralType,
9+
PartialType, DeletedType, UninhabitedType, TypeType, true_or_false, TypeOfAny,
1010
)
1111
from mypy.maptype import map_instance_to_supertype
1212
from mypy.subtypes import (
@@ -267,6 +267,9 @@ def visit_typeddict_type(self, t: TypedDictType) -> Type:
267267
else:
268268
return self.default(self.s)
269269

270+
def visit_literal_type(self, t: LiteralType) -> Type:
271+
raise NotImplementedError()
272+
270273
def visit_partial_type(self, t: PartialType) -> Type:
271274
# We only have partial information so we can't decide the join result. We should
272275
# never get here.

mypy/meet.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from mypy.types import (
88
Type, AnyType, TypeVisitor, UnboundType, NoneTyp, TypeVarType, Instance, CallableType,
99
TupleType, TypedDictType, ErasedType, UnionType, PartialType, DeletedType,
10-
UninhabitedType, TypeType, TypeOfAny, Overloaded, FunctionLike,
10+
UninhabitedType, TypeType, TypeOfAny, Overloaded, FunctionLike, LiteralType,
1111
)
1212
from mypy.subtypes import (
1313
is_equivalent, is_subtype, is_protocol_implementation, is_callable_compatible,
@@ -520,6 +520,9 @@ def visit_typeddict_type(self, t: TypedDictType) -> Type:
520520
else:
521521
return self.default(self.s)
522522

523+
def visit_literal_type(self, t: LiteralType) -> Type:
524+
raise NotImplementedError()
525+
523526
def visit_partial_type(self, t: PartialType) -> Type:
524527
# We can't determine the meet of partial types. We should never get here.
525528
assert False, 'Internal error'

mypy/sametypes.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from mypy.types import (
44
Type, UnboundType, AnyType, NoneTyp, TupleType, TypedDictType,
55
UnionType, CallableType, TypeVarType, Instance, TypeVisitor, ErasedType,
6-
Overloaded, PartialType, DeletedType, UninhabitedType, TypeType
6+
Overloaded, PartialType, DeletedType, UninhabitedType, TypeType, LiteralType,
77
)
88

99

@@ -114,6 +114,14 @@ def visit_typeddict_type(self, left: TypedDictType) -> bool:
114114
else:
115115
return False
116116

117+
def visit_literal_type(self, left: LiteralType) -> bool:
118+
if isinstance(self.right, LiteralType):
119+
if left.value != self.right.value:
120+
return False
121+
return is_same_type(left.fallback, self.right.fallback)
122+
else:
123+
return False
124+
117125
def visit_union_type(self, left: UnionType) -> bool:
118126
if isinstance(self.right, UnionType):
119127
# Check that everything in left is in right

mypy/server/astdiff.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class level -- these are handled at attribute level (say, 'mod.Cls.method'
5959
from mypy.types import (
6060
Type, TypeVisitor, UnboundType, AnyType, NoneTyp, UninhabitedType,
6161
ErasedType, DeletedType, Instance, TypeVarType, CallableType, TupleType, TypedDictType,
62-
UnionType, Overloaded, PartialType, TypeType
62+
UnionType, Overloaded, PartialType, TypeType, LiteralType,
6363
)
6464
from mypy.util import get_prefix
6565

@@ -315,6 +315,9 @@ def visit_typeddict_type(self, typ: TypedDictType) -> SnapshotItem:
315315
required = tuple(sorted(typ.required_keys))
316316
return ('TypedDictType', items, required)
317317

318+
def visit_literal_type(self, typ: LiteralType) -> SnapshotItem:
319+
return ('LiteralType', typ.value, snapshot_type(typ.fallback))
320+
318321
def visit_union_type(self, typ: UnionType) -> SnapshotItem:
319322
# Sort and remove duplicates so that we can use equality to test for
320323
# equivalent union type snapshots.

mypy/server/astmerge.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
from mypy.types import (
5959
Type, SyntheticTypeVisitor, Instance, AnyType, NoneTyp, CallableType, DeletedType, PartialType,
6060
TupleType, TypeType, TypeVarType, TypedDictType, UnboundType, UninhabitedType, UnionType,
61-
Overloaded, TypeVarDef, TypeList, CallableArgument, EllipsisType, StarType
61+
Overloaded, TypeVarDef, TypeList, CallableArgument, EllipsisType, StarType, LiteralType,
6262
)
6363
from mypy.util import get_prefix, replace_object_state
6464
from mypy.typestate import TypeState
@@ -391,6 +391,9 @@ def visit_typeddict_type(self, typ: TypedDictType) -> None:
391391
value_type.accept(self)
392392
typ.fallback.accept(self)
393393

394+
def visit_literal_type(self, typ: LiteralType) -> None:
395+
typ.fallback.accept(self)
396+
394397
def visit_unbound_type(self, typ: UnboundType) -> None:
395398
for arg in typ.args:
396399
arg.accept(self)

0 commit comments

Comments
 (0)