Skip to content

Commit 94bf64b

Browse files
authored
Do not repor trivial narrowing as a change in binder (#20862)
Fixes #20816 This makes `--allow-redefinition-new` ~10% faster (or maybe more if you have too many loops in your code). The idea is quite simple: there is no difference between no narrowing, and narrowing to type that is a variable declared type. This doesn't really make a difference for regular mode, IIUC because there is a "fall through", i.e. zero-iterations case, but this doesn't work with `bind_all = True`. As a result we used to accept _every_ loop with an assignment in it at lest twice with `--allow-redefinition-new` (which includes assignment to iteration variable in for-loop). Note that `declaration_type` may be `None` if there is a partial type, but we already track partial types in accept loop separately, so we don't need to report them as changed here as well.
1 parent 2aafc9b commit 94bf64b

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

mypy/binder.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,22 @@ def update_from_options(self, frames: list[Frame]) -> bool:
392392
type = simplified
393393
if current_value is None or not is_same_type(type, current_value.type):
394394
self._put(key, type, from_assignment=True)
395-
changed = True
395+
if current_value is not None or extract_var_from_literal_hash(key) is None:
396+
# We definitely learned something new
397+
changed = True
398+
else:
399+
# If there is no current value compare with the declaration. This prevents
400+
# reporting false changes in cases like this:
401+
# x: int
402+
# if foo():
403+
# x = 1
404+
# else:
405+
# x = 2
406+
# We check partial types and widening in accept_loop() separately, so
407+
# this should be safe.
408+
changed = declaration_type is not None and not is_same_type(
409+
type, declaration_type
410+
)
396411

397412
self.frames[-1].unreachable = not frames
398413

0 commit comments

Comments
 (0)