Skip to content

Assigning a variable to the result of an untyped method removes any existing type constraints #3724

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

Closed
rowillia opened this issue Jul 17, 2017 · 6 comments · Fixed by #18538

Comments

@rowillia
Copy link
Contributor

from typing import Any, Optional

def foo() -> Optional[int]:
    return 42

raz: Any

def bar() -> int:
    x = foo()
    if isinstance(x, int):
        reveal_type(x)
        x = raz()
        reveal_type(x)
        x = x + 42
    return 0
$ python3.6 -m mypy --strict-optional test_optional_assign.py
test_optional_assign.py:11: error: Revealed type is 'builtins.int'
test_optional_assign.py:13: error: Revealed type is 'Union[builtins.int, builtins.None]'
test_optional_assign.py:14: error: Unsupported operand types for + ("Optional[int]" and "int")

I would have expected the revealed type at like 13 to be Any.

@ilevkivskyi
Copy link
Member

I would have expected the revealed type at like 13 to be Any.

I think you mean "to be int". If yes then this is a binder problem. It may be related to #3526 and recently merged #3361. But unlike the former, this issues is probably easy to solve (I would guess just a small binder bug).

@rowillia
Copy link
Contributor Author

@ilevkivskyi I actually did expect the type to be Any. The other case where this is biting us is below:

from typing import Any, Optional

def foo() -> Optional[int]:
    return 42

raz: Any

def bar() -> int:
    x = foo()
    if x is None:
        x = raz()
    return x

In this case raz really will set x to some integer but it's impossible to get this code to typecheck.

@ilevkivskyi
Copy link
Member

OK, following our short discussion on gitter I think that Any is fine here. As I mentioned earlier in #3526, I am fine with the idea of rebinding to Any (especially inside unions).

@ilevkivskyi
Copy link
Member

@msullivan I thought your PR #5629 could fix this as well, but it looks like the original example in this issue is still failing. Can we also special case this? Or this would require a more general fix?

@erictraut
Copy link

I think mypy's current behavior is correct here. The (implicitly) declared type of x is int | None. Assigning a value of type Any to x should be permitted (for reasons of gradual typing), but this assignment shouldn't change the type of x. Its type should not be narrowed to Any in this case.

@hauntsaninja hauntsaninja closed this as not planned Won't fix, can't repro, duplicate, stale Aug 28, 2023
@ilevkivskyi
Copy link
Member

No mypy's behavior is not correct. Changing any precise type to Any should never create a new error. The example below works, and so the original one should too.

from typing import Any, Optional

def foo() -> Optional[int]:
    return 42

def bar() -> int:
    x = foo()
    if isinstance(x, int):
        reveal_type(x)
        x = 15
        reveal_type(x)
        x = x + 42
    return 0

@ilevkivskyi ilevkivskyi reopened this Aug 28, 2023
x612skm pushed a commit to x612skm/mypy-dev that referenced this issue Feb 24, 2025
This would be more consistent with what we already do for ternary
expressions. Note the change in match test results from match logic not
handling well the situation when initial type is a union. A possible
workaround would be to force "collapsing" union of tuples back into a
tuple with union, but it is not easy and was planning to do some cleanup
in the match handling as well (in particular it uses joins instead of
unions in a way that will be inconsistent with new binder behavior). I
want to put the switch from join to union for match statement in a
separate PR.

Note I also simplify a bunch of special-casing around `Any` in the
binder that existed mostly because `join(Any, X) == Any`.
Fixes python#3724
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants