From 3adb6e3446db1329faa424361fca75d250ee1327 Mon Sep 17 00:00:00 2001 From: Hugues Bruant Date: Sun, 1 May 2022 00:10:11 -0700 Subject: [PATCH] checkexpr: speedup typechecking of container literals with tuple entries `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 #9427 --- mypy/checkexpr.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index bd69c1427dce..cea44c6c17db 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -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. @@ -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: @@ -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]) @@ -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: @@ -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