Skip to content

Commit 4eb09ac

Browse files
committed
Force list expression to infer Union type of member types.
1 parent d39eacc commit 4eb09ac

File tree

1 file changed

+27
-5
lines changed

1 file changed

+27
-5
lines changed

mypy/checkexpr.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5017,15 +5017,22 @@ def fast_container_type(
50175017
return ct
50185018

50195019
def check_lst_expr(self, e: ListExpr | SetExpr | TupleExpr, fullname: str, tag: str) -> Type:
5020-
# fast path
5020+
# Fast path
50215021
t = self.fast_container_type(e, fullname)
50225022
if t:
50235023
return t
5024+
if isinstance(e, ListExpr):
5025+
item_types = [self.accept(item) for item in e.items]
5026+
# Empty list, default to Any
5027+
if not item_types:
5028+
item_type = AnyType(TypeOfAny.from_empty_collection)
5029+
else:
5030+
# Attempt to infer a common supertype
5031+
item_type = self.infer_item_type(item_types)
5032+
return self.chk.named_generic_type(fullname, [item_type])
50245033

5025-
# Translate into type checking a generic function call.
5026-
# Used for list and set expressions, as well as for tuples
5027-
# containing star expressions that don't refer to a
5028-
# Tuple. (Note: "lst" stands for list-set-tuple. :-)
5034+
# For SetExpr and TupleExpr, use existing logic
5035+
# Translate into type checking a generic function call
50295036
tv = TypeVarType(
50305037
"T",
50315038
"T",
@@ -5051,6 +5058,21 @@ def check_lst_expr(self, e: ListExpr | SetExpr | TupleExpr, fullname: str, tag:
50515058
)[0]
50525059
return remove_instance_last_known_values(out)
50535060

5061+
def infer_item_type(self, item_types: List[Type]) -> Type:
5062+
"""Infer the item type for a list based on its elements."""
5063+
joined_type = self.chk.join_types(*item_types)
5064+
proper_joined = get_proper_type(joined_type)
5065+
if (
5066+
isinstance(proper_joined, Instance)
5067+
and proper_joined.type.fullname == "builtins.object"
5068+
and len(set(map(type, item_types))) > 1
5069+
):
5070+
# No common supertype other than 'object', so use a Union of the item types
5071+
return UnionType.make_simplified_union(item_types)
5072+
else:
5073+
# Use the common supertype
5074+
return joined_type
5075+
50545076
def tuple_context_matches(self, expr: TupleExpr, ctx: TupleType) -> bool:
50555077
ctx_unpack_index = find_unpack_in_list(ctx.items)
50565078
if ctx_unpack_index is None:

0 commit comments

Comments
 (0)