Skip to content

Unreachability should work for constrained type vars #19256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
A5rocks opened this issue Jun 8, 2025 · 1 comment
Open

Unreachability should work for constrained type vars #19256

A5rocks opened this issue Jun 8, 2025 · 1 comment
Assignees

Comments

@A5rocks
Copy link
Collaborator

A5rocks commented Jun 8, 2025

Feature

Unreachability should be checked for constrained type vars.

Pitch

It would be nice if this raised an error when run with --warn-unreachable:

from typing import TypeVar

U = TypeVar('U', int, str)

def f(u: U) -> U:
    if u is None:
        print("whoa!!")
    
    return u

To implement this feature, I think we need to store the spans of unreachability for each run, then find the intersection. I thought for a while that we could just treat constrained type variables as if they were bound to the union of constraints, but things like #9424 will happen for things that aren't final (unlike None).

@tyralla
Copy link
Collaborator

tyralla commented Jun 12, 2025

I investigated a little, and this limitation seems to have been known for a while:

def test2(x: T2) -> T2:
if isinstance(x, int):
reveal_type(x) # N: Revealed type is "builtins.int"
else:
reveal_type(x) # N: Revealed type is "builtins.str"
if False:
# This is unreachable, but we don't report an error, unfortunately.
# The presence of the TypeVar with values unfortunately currently shuts
# down type-checking for this entire function.
# TODO: Find a way of removing this limitation
reveal_type(x)
return x

mypy/mypy/checker.py

Lines 1467 to 1475 in 8241059

# We also suppress reachability warnings when we use TypeVars with value
# restrictions: we only want to report a warning if a certain statement is
# marked as being suppressed in *all* of the expansions, but we currently
# have no good way of doing this.
#
# TODO: Find a way of working around this limitation
if _is_empty_generator_function(item) or len(expanded) >= 2:
self.binder.suppress_unreachable_warnings()
self.accept(item.body)

I experimented with the IterationErrorWatcher proposed in #19270 and was successful in the first simple attempt. However, as many existing tests would require adjustment and some new ones should be introduced (which might reveal the need to adjust the method eventually), I will wait to work on it until #19270 is accepted.

By the way, aren't classes with type variables with value constraints a problem, too?

@tyralla tyralla self-assigned this Jun 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants