Skip to content

Commit

Permalink
checkexpr: speedup typechecking of container literals with tuple entries
Browse files Browse the repository at this point in the history
`fast_dict_type` and `fast_container_type` only allowed Instance but not Tuple of Instances
which was mostly an oversight, as opposed to an intentional omission.

For python#9427
  • Loading branch information
huguesb committed May 1, 2022
1 parent a56ebec commit 3adb6e3
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions mypy/checkexpr.py
Expand Up @@ -118,6 +118,16 @@ class TooManyUnions(Exception):
"""


def allow_fast_container_literal(t: ProperType) -> bool:
return (
isinstance(t, Instance)
or (
isinstance(t, TupleType)
and all(allow_fast_container_literal(get_proper_type(it)) for it in t.items)
)
)


def extract_refexpr_names(expr: RefExpr) -> Set[str]:
"""Recursively extracts all module references from a reference expression.
Expand Down Expand Up @@ -3265,7 +3275,7 @@ def fast_container_type(
Limitations:
- no active type context
- no star expressions
- the joined type of all entries must be an Instance type
- the joined type of all entries must be an Instance or Tuple type
"""
ctx = self.type_context[-1]
if ctx:
Expand All @@ -3277,7 +3287,7 @@ def fast_container_type(
return None
values.append(self.accept(item))
vt = join.join_type_list(values)
if not isinstance(vt, Instance):
if not allow_fast_container_literal(vt):
return None
return self.chk.named_generic_type(container_fullname, [vt])

Expand Down Expand Up @@ -3377,7 +3387,7 @@ def fast_dict_type(self, e: DictExpr) -> Optional[Type]:
Limitations:
- no active type context
- only supported star expressions are other dict instances
- the joined types of all keys and values must be Instance types
- the joined types of all keys and values must be Instance or Tuple types
"""
ctx = self.type_context[-1]
if ctx:
Expand All @@ -3401,7 +3411,7 @@ def fast_dict_type(self, e: DictExpr) -> Optional[Type]:
values.append(self.accept(value))
kt = join.join_type_list(keys)
vt = join.join_type_list(values)
if not (isinstance(kt, Instance) and isinstance(vt, Instance)):
if not (allow_fast_container_literal(kt) and allow_fast_container_literal(vt)):
return None
if stargs and (stargs[0] != kt or stargs[1] != vt):
return None
Expand Down

0 comments on commit 3adb6e3

Please sign in to comment.