Describe the Bug
isinstance() narrowing of a union variable silently stops working when an earlier sibling branch in the same if/elif/else chain narrows a different variable with isinstance() and returns. The later narrowing leaves the union untouched, producing false missing-attribute errors.
This is a regression: it works correctly in pyrefly 1.0.0 and is broken in 1.1.0 (git bisect came up with 86f0da7 being the culprit).
Inside if isinstance(value, int):, value should narrow to int, as it does in 1.0.0. The isinstance(other, int) check on the unrelated other in the earlier elif should have no effect on value.
Repro
(same as sandbox link)
from typing import reveal_type
def f(cond: bool, other: object, value: int | str) -> None:
if cond:
pass
elif isinstance(other, int): # narrows a DIFFERENT variable, in a branch that returns
return
else:
return
reveal_type(value) # int | str
if isinstance(value, int):
reveal_type(value) # BUG: int | str (should be: int)
value.bit_length() # false error: `str` has no attribute `bit_length`
Expected / 1.0.0 behavior
revealed type: int | str
revealed type: int
0 errors
Actual behavior
revealed type: int | str
revealed type: int | str <- should be `int`
ERROR Object of class `str` has no attribute `bit_length` [missing-attribute]
Sandbox Link
https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAEALqcROgOZ0Q3G6UN2UYANxiooAfSbEYAHXRzMMMHTAAKAMa4siOnlxQANHVwMAFjEo7c2AFYx1DI0LEBXGDtb8APnTgNKAJR0ALQAfHQAclrucnRxnMqa2rHxqcSocHApcTBQEMoQcKx%2BGOowqibmlEaeATpxAMR06KiU1ADucHSodAAiAJIAYoMAogBKIxEAKnTOlBCo2LA16N26lKWmjKao-IIMLpToWaup8fuH8qc5UHAx12cXR3LZAsKiElLlzlBuQWcAuhNTx0Hx%2BSivfKcIrHBilb6uGArBh1V6pQQiMSSZgI34wf6ApoAIQAqgBxDzoby%2BfzxVRwUy4FxQTC6dycKkBNHxH5uQjYCAMcSwdhmVQEgFNMBiO50CzUSx0AAG4KVdB2XXQuG6DH8EGwLgYMGVAqFIrYZiVIAMIDIgjAUFIhAYtCgFCaAAVSPbHb4MDgCHQkpA2IddhAtIQ5E0AMowY2mXXEOCIAD0qbtSkdhF4bFTMHQqcwuHUcFTwYgoY2DAjhZUvG6zmgi1gQa0IbDNa0xmIXeOUfQIAAvjbUA4ICJBtAYBQ0Fg8EQyMOgA
(Only applicable for extension issues) IDE Information
No response
Describe the Bug
isinstance()narrowing of a union variable silently stops working when an earlier sibling branch in the sameif/elif/elsechain narrows a different variable withisinstance()and returns. The later narrowing leaves the union untouched, producing falsemissing-attributeerrors.This is a regression: it works correctly in pyrefly 1.0.0 and is broken in 1.1.0 (git bisect came up with 86f0da7 being the culprit).
Inside
if isinstance(value, int):,valueshould narrow toint, as it does in 1.0.0. Theisinstance(other, int)check on the unrelatedotherin the earlierelifshould have no effect onvalue.Repro
(same as sandbox link)
Expected / 1.0.0 behavior
Actual behavior
Sandbox Link
https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAEALqcROgOZ0Q3G6UN2UYANxiooAfSbEYAHXRzMMMHTAAKAMa4siOnlxQANHVwMAFjEo7c2AFYx1DI0LEBXGDtb8APnTgNKAJR0ALQAfHQAclrucnRxnMqa2rHxqcSocHApcTBQEMoQcKx%2BGOowqibmlEaeATpxAMR06KiU1ADucHSodAAiAJIAYoMAogBKIxEAKnTOlBCo2LA16N26lKWmjKao-IIMLpToWaup8fuH8qc5UHAx12cXR3LZAsKiElLlzlBuQWcAuhNTx0Hx%2BSivfKcIrHBilb6uGArBh1V6pQQiMSSZgI34wf6ApoAIQAqgBxDzoby%2BfzxVRwUy4FxQTC6dycKkBNHxH5uQjYCAMcSwdhmVQEgFNMBiO50CzUSx0AAG4KVdB2XXQuG6DH8EGwLgYMGVAqFIrYZiVIAMIDIgjAUFIhAYtCgFCaAAVSPbHb4MDgCHQkpA2IddhAtIQ5E0AMowY2mXXEOCIAD0qbtSkdhF4bFTMHQqcwuHUcFTwYgoY2DAjhZUvG6zmgi1gQa0IbDNa0xmIXeOUfQIAAvjbUA4ICJBtAYBQ0Fg8EQyMOgA
(Only applicable for extension issues) IDE Information
No response