Skip to content

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

Closed

Description

@rowillia
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.

Activity

  1. ilevkivskyi commented on Jul 17, 2017

    @ilevkivskyi
    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).

  2. rowillia commented on Jul 17, 2017

    @rowillia
    ContributorAuthor

    @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.

  3. ilevkivskyi commented on Jul 17, 2017

    @ilevkivskyi
    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).

  4. ilevkivskyi commented on Dec 7, 2018

    @ilevkivskyi
    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?

  5. erictraut commented on Aug 10, 2023

    @erictraut

    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.

  6. ilevkivskyi commented on Aug 28, 2023

    @ilevkivskyi
    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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions