Skip to content

Commit 3aa9472

Browse files
committed
Apply same treatment to dict literals
1 parent 46f7825 commit 3aa9472

File tree

2 files changed

+28
-17
lines changed

2 files changed

+28
-17
lines changed

mypy/checkexpr.py

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5092,21 +5092,22 @@ def fast_container_type(
50925092
if typ not in values:
50935093
values.append(typ)
50945094

5095-
if len(values) == 1 and not self.chk.current_node_deferred:
5096-
# If only one non-duplicate item remains, there's no need to run the whole
5097-
# inference cycle over it. This helps in pathological cases where items
5098-
# are complex overloads.
5099-
# https://github.com/python/mypy/issues/14718
5100-
vt = values[0]
5101-
else:
5102-
vt = join.join_type_list(values)
5103-
if not allow_fast_container_literal(vt):
5104-
self.resolved_type[e] = NoneType()
5105-
return None
5095+
vt = self._first_or_join_fast_item(values)
5096+
if vt is None:
5097+
self.resolved_type[e] = NoneType()
5098+
return None
51065099
ct = self.chk.named_generic_type(container_fullname, [vt])
51075100
self.resolved_type[e] = ct
51085101
return ct
51095102

5103+
def _first_or_join_fast_item(self, items: list[Type]) -> Type | None:
5104+
if len(items) == 1 and not self.chk.current_node_deferred:
5105+
return items[0]
5106+
typ = join.join_type_list(items)
5107+
if not allow_fast_container_literal(typ):
5108+
return None
5109+
return typ
5110+
51105111
def check_lst_expr(self, e: ListExpr | SetExpr | TupleExpr, fullname: str, tag: str) -> Type:
51115112
# fast path
51125113
t = self.fast_container_type(e, fullname)
@@ -5293,13 +5294,23 @@ def fast_dict_type(self, e: DictExpr) -> Type | None:
52935294
self.resolved_type[e] = NoneType()
52945295
return None
52955296
else:
5296-
keys.append(self.accept(key))
5297-
values.append(self.accept(value))
5298-
kt = join.join_type_list(keys)
5299-
vt = join.join_type_list(values)
5300-
if not (allow_fast_container_literal(kt) and allow_fast_container_literal(vt)):
5297+
key_t = self.accept(key)
5298+
if key_t not in keys:
5299+
keys.append(key_t)
5300+
value_t = self.accept(value)
5301+
if value_t not in values:
5302+
values.append(value_t)
5303+
5304+
kt = self._first_or_join_fast_item(keys)
5305+
if kt is None:
53015306
self.resolved_type[e] = NoneType()
53025307
return None
5308+
5309+
vt = self._first_or_join_fast_item(values)
5310+
if vt is None:
5311+
self.resolved_type[e] = NoneType()
5312+
return None
5313+
53035314
if stargs and (stargs[0] != kt or stargs[1] != vt):
53045315
self.resolved_type[e] = NoneType()
53055316
return None

test-data/unit/check-selftype.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2018,7 +2018,7 @@ class Ben(Object):
20182018
}
20192019
@classmethod
20202020
def doit(cls) -> Foo:
2021-
reveal_type(cls.MY_MAP) # N: Revealed type is "builtins.dict[builtins.str, def [Self <: __main__.Foo] (self: Self`4) -> Self`4]"
2021+
reveal_type(cls.MY_MAP) # N: Revealed type is "builtins.dict[builtins.str, def [Self <: __main__.Foo] (self: Self`1) -> Self`1]"
20222022
foo_method = cls.MY_MAP["foo"]
20232023
return foo_method(Foo())
20242024
[builtins fixtures/isinstancelist.pyi]

0 commit comments

Comments
 (0)