Skip to content

Commit 109e15d

Browse files
authored
Change some sequence components in types from lists to tuples (#8945)
This cuts down on memory a bit by avoiding the separate allocation inside lists and by allowing all empty sequences to share the empty tuple.
1 parent a67b4af commit 109e15d

File tree

9 files changed

+20
-17
lines changed

9 files changed

+20
-17
lines changed

mypy/checkexpr.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3135,7 +3135,9 @@ class LongName(Generic[T]): ...
31353135
# This type is invalid in most runtime contexts, give it an 'object' type.
31363136
return self.named_type('builtins.object')
31373137

3138-
def apply_type_arguments_to_callable(self, tp: Type, args: List[Type], ctx: Context) -> Type:
3138+
def apply_type_arguments_to_callable(
3139+
self, tp: Type, args: Sequence[Type], ctx: Context
3140+
) -> Type:
31393141
"""Apply type arguments to a generic callable type coming from a type object.
31403142
31413143
This will first perform type arguments count checks, report the

mypy/expandtype.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def expand_type_by_instance(typ: Type, instance: Instance) -> Type:
2020
"""Substitute type variables in type using values from an Instance.
2121
Type variables are considered to be bound by the class declaration."""
2222
# TODO: use an overloaded signature? (ProperType stays proper after expansion.)
23-
if instance.args == []:
23+
if not instance.args:
2424
return typ
2525
else:
2626
variables = {} # type: Dict[TypeVarId, Type]

mypy/exprtotype.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def expr_to_unanalyzed_type(expr: Expression, _parent: Optional[Expression] = No
6161
args = expr.index.items
6262
else:
6363
args = [expr.index]
64-
base.args = [expr_to_unanalyzed_type(arg, expr) for arg in args]
64+
base.args = tuple(expr_to_unanalyzed_type(arg, expr) for arg in args)
6565
if not base.args:
6666
base.empty_tuple_index = True
6767
return base

mypy/messages.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1595,7 +1595,7 @@ def format(typ: Type) -> str:
15951595
base_str = itype.type.fullname
15961596
else:
15971597
base_str = itype.type.name
1598-
if itype.args == []:
1598+
if not itype.args:
15991599
# No type arguments, just return the type name
16001600
return base_str
16011601
elif itype.type.fullname == 'builtins.tuple':

mypy/semanal_shared.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,4 +221,4 @@ def calculate_tuple_fallback(typ: TupleType) -> None:
221221
"""
222222
fallback = typ.partial_fallback
223223
assert fallback.type.fullname == 'builtins.tuple'
224-
fallback.args[0] = join.join_type_list(list(typ.items))
224+
fallback.args = (join.join_type_list(list(typ.items)),) + fallback.args[1:]

mypy/suggestions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ def visit_instance(self, t: Instance) -> str:
805805

806806
if (mod, obj) == ('builtins', 'tuple'):
807807
mod, obj = 'typing', 'Tuple[' + t.args[0].accept(self) + ', ...]'
808-
elif t.args != []:
808+
elif t.args:
809809
obj += '[{}]'.format(self.list_str(t.args))
810810

811811
if mod_obj == ('builtins', 'unicode'):

mypy/typeanal.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from contextlib import contextmanager
66
from mypy.ordered_dict import OrderedDict
77

8-
from typing import Callable, List, Optional, Set, Tuple, Iterator, TypeVar, Iterable
8+
from typing import Callable, List, Optional, Set, Tuple, Iterator, TypeVar, Iterable, Sequence
99
from typing_extensions import Final
1010
from mypy_extensions import DefaultNamedArg
1111

@@ -324,7 +324,8 @@ def get_omitted_any(self, typ: Type, fullname: Optional[str] = None) -> AnyType:
324324
disallow_any = not self.is_typeshed_stub and self.options.disallow_any_generics
325325
return get_omitted_any(disallow_any, self.fail, self.note, typ, fullname)
326326

327-
def analyze_type_with_type_info(self, info: TypeInfo, args: List[Type], ctx: Context) -> Type:
327+
def analyze_type_with_type_info(
328+
self, info: TypeInfo, args: Sequence[Type], ctx: Context) -> Type:
328329
"""Bind unbound type when were able to find target TypeInfo.
329330
330331
This handles simple cases like 'int', 'modname.UserClass[str]', etc.
@@ -951,7 +952,7 @@ def fix_instance(t: Instance, fail: MsgCallback, note: MsgCallback,
951952
else:
952953
fullname = t.type.fullname
953954
any_type = get_omitted_any(disallow_any, fail, note, t, fullname, unexpanded_type)
954-
t.args = [any_type] * len(t.type.type_vars)
955+
t.args = (any_type,) * len(t.type.type_vars)
955956
return
956957
# Invalid number of type parameters.
957958
n = len(t.type.type_vars)
@@ -968,7 +969,7 @@ def fix_instance(t: Instance, fail: MsgCallback, note: MsgCallback,
968969
# Construct the correct number of type arguments, as
969970
# otherwise the type checker may crash as it expects
970971
# things to be right.
971-
t.args = [AnyType(TypeOfAny.from_error) for _ in t.type.type_vars]
972+
t.args = tuple(AnyType(TypeOfAny.from_error) for _ in t.type.type_vars)
972973
t.invalid = True
973974

974975

mypy/types.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ class UnboundType(ProperType):
397397

398398
def __init__(self,
399399
name: Optional[str],
400-
args: Optional[List[Type]] = None,
400+
args: Optional[Sequence[Type]] = None,
401401
line: int = -1,
402402
column: int = -1,
403403
optional: bool = False,
@@ -410,7 +410,7 @@ def __init__(self,
410410
args = []
411411
assert name is not None
412412
self.name = name
413-
self.args = args
413+
self.args = tuple(args)
414414
# Should this type be wrapped in an Optional?
415415
self.optional = optional
416416
# Special case for X[()]
@@ -432,7 +432,7 @@ def __init__(self,
432432
self.original_str_fallback = original_str_fallback
433433

434434
def copy_modified(self,
435-
args: Bogus[Optional[List[Type]]] = _dummy,
435+
args: Bogus[Optional[Sequence[Type]]] = _dummy,
436436
) -> 'UnboundType':
437437
if args is _dummy:
438438
args = self.args
@@ -731,12 +731,12 @@ class Instance(ProperType):
731731

732732
__slots__ = ('type', 'args', 'erased', 'invalid', 'type_ref', 'last_known_value')
733733

734-
def __init__(self, typ: mypy.nodes.TypeInfo, args: List[Type],
734+
def __init__(self, typ: mypy.nodes.TypeInfo, args: Sequence[Type],
735735
line: int = -1, column: int = -1, erased: bool = False,
736736
last_known_value: Optional['LiteralType'] = None) -> None:
737737
super().__init__(line, column)
738738
self.type = typ
739-
self.args = args
739+
self.args = tuple(args)
740740
self.type_ref = None # type: Optional[str]
741741

742742
# True if result of type variable substitution
@@ -2013,7 +2013,7 @@ def visit_instance(self, t: Instance) -> str:
20132013

20142014
if t.erased:
20152015
s += '*'
2016-
if t.args != []:
2016+
if t.args:
20172017
s += '[{}]'.format(self.list_str(t.args))
20182018
if self.id_mapper:
20192019
s += '<{}>'.format(self.id_mapper.id(t.type))

test-data/unit/plugins/dyn_class.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def replace_col_hook(ctx):
3939
if new_sym:
4040
new_info = new_sym.node
4141
assert isinstance(new_info, TypeInfo)
42-
node.type = Instance(new_info, node.type.args.copy(),
42+
node.type = Instance(new_info, node.type.args,
4343
node.type.line,
4444
node.type.column)
4545

0 commit comments

Comments
 (0)