Skip to content
New issue

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

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

Already on GitHub? # to your account

False positive: variable re-assigned with different type treated as of previous type #9700

Closed
ponbaton opened this issue Nov 5, 2020 · 8 comments
Labels
bug mypy got something wrong

Comments

@ponbaton
Copy link

ponbaton commented Nov 5, 2020

Bug Report

If you reassign a variable with a different (probably compatible) type, mypy still treats it as if it did not change the type

To Reproduce

Analyze this:

from typing import Tuple


class C:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @classmethod
    def other_ctor(cls, x, y):
        return cls(x, y)


def will_fail(arg: Tuple[int, int]):
    arg = C.other_ctor(*arg)
    print(arg.x + arg.y)

Expected Behavior

Success: no issues found in 1 source file

Actual Behavior

>mypy break_mypy\failure.py
break_mypy\failure.py:16: error: "Tuple[int, int]" has no attribute "x"
break_mypy\failure.py:16: error: "Tuple[int, int]" has no attribute "y"
Found 2 errors in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 0.790
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): default, freshly installed
  • Python version used: python 3.6.6 @ Win10 v1909, python 3.7.9 @ Ubuntu 16.04

Additional info

This version without classmethod constructor gives yet another error:

from typing import Tuple


class C:
    def __init__(self, x, y):
        self.x = x
        self.y = y


def will_fail(arg: Tuple[int, int]):
    arg = C(*arg)
    print(arg.x + arg.y)
break_mypy\failure.py:11: error: Incompatible types in assignment (expression has type "C", variable has type "Tuple[int, int]")
break_mypy\failure.py:12: error: "Tuple[int, int]" has no attribute "x"
break_mypy\failure.py:12: error: "Tuple[int, int]" has no attribute "y"
Found 3 errors in 1 file (checked 1 source file)

C was originally a wrapper subclass of namedtuple, but I removed it while working on the MVE.

One more example with namedtuple:

from collections import namedtuple
from typing import Tuple


class C(namedtuple('CNt', 'x y')):
    @classmethod
    def other_ctor(cls, x, y):
        return cls(x, y)


def will_not_fail(arg: Tuple[int, int]):
    arg = C(*arg)
    print(arg.x + arg.y)


def will_fail(arg: Tuple[int, int]):
    arg = C.other_ctor(*arg)
    print(arg.x + arg.y)
break_mypy\failure.py:18: error: "Tuple[int, int]" has no attribute "x"
break_mypy\failure.py:18: error: "Tuple[int, int]" has no attribute "y"
Found 2 errors in 1 file (checked 1 source file)
@ponbaton ponbaton added the bug mypy got something wrong label Nov 5, 2020
@JelleZijlstra
Copy link
Member

Try using the --allow-redefinition flag.

@ponbaton
Copy link
Author

ponbaton commented Nov 6, 2020

Hmm, it works, thanks. The original error messages are a bit misleading though: most of the time the do not even point to redefinition problems

Is this the indended behavior? Is it documented somewhere?

@ponbaton
Copy link
Author

ponbaton commented Nov 6, 2020

The behavior when mypy does not always detect fields in the re-assigned type (sometimes it does, sometimes it does not) still looks like a bug to me. Have a look at the example with namedtuple

@ponbaton
Copy link
Author

ponbaton commented Nov 6, 2020

@JelleZijlstra, could you re-open the issue?

@JelleZijlstra
Copy link
Member

That's just because mypy keeps the original declared type.

@ponbaton
Copy link
Author

ponbaton commented Nov 6, 2020

Then again: is it documented behavior or an implementation detail? I think it is very confusing and should be documented or fixed

@JelleZijlstra JelleZijlstra reopened this Nov 16, 2020
@JelleZijlstra
Copy link
Member

OK, let's reopen as a documentation issue.

@hauntsaninja
Copy link
Collaborator

I believe this is just #2008 again. We recently had a big discussion about this, and agreed that the behaviour needs to change.
There's also an open issue already for documentation of the existing behaviour: #7252

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

3 participants