Skip to content

Wrong type hint after unpacking/swapping #9731

Open

Description

@NiklasRosenstein

Bug Report

Unpacking a tuple in the below scenario results in wrong assumed types.

To Reproduce

import typing as t

def spam(val: t.Union[t.Type, None] = None) -> None:

  def eggs(type_: t.Type) -> None:
    pass

  reveal_type(val)
  if isinstance(val, type):
    reveal_type(val)
    val, foo = None, val
    reveal_type(val)
    reveal_type(foo)
    return eggs(foo)

Expected Behavior

After the line val, foo = None, val, I would expect that

  1. val has type None (ok)
  2. foo has type Type[Any]
  3. the call to eggs() passes

Actual Behavior

$ mypy test.py 
test.py:9: note: Revealed type is 'Union[Type[Any], None]'
test.py:11: note: Revealed type is 'Type[Any]'
test.py:13: note: Revealed type is 'None'
test.py:14: note: Revealed type is 'None'
test.py:15: error: Argument 1 to "eggs" has incompatible type "None"; expected "Type[Any]"
Found 1 error in 1 file (checked 1 source file)

This does not match with my expectations 2 and 3.

Your Environment

Python 3.9
Mypy 0.790
MacOS 10.14.6

Activity

  1. changed the title [-]Wrong type hint after unpacking[/-] [+]Wrong type hint after unpacking/swapping[/+] on Nov 18, 2020
  2. NiklasRosenstein commented on Nov 18, 2020

    @NiklasRosenstein
    Author

    Splitting the swap/unpacking into two lines works:

    import typing as t
    
    def spam(val: t.Union[t.Type, None] = None) -> None:
    
      def eggs(type_: t.Type) -> None:
        pass
    
      reveal_type(val)
      if isinstance(val, type):
        reveal_type(val)
        foo = val
        val = None
        reveal_type(val)
        reveal_type(foo)
        return eggs(foo)
    $ mypy test.py 
    test.py:9: note: Revealed type is 'Union[Type[Any], None]'
    test.py:11: note: Revealed type is 'Type[Any]'
    test.py:14: note: Revealed type is 'None'
    test.py:15: note: Revealed type is 'Type[Any]'
    
  3. JelleZijlstra commented on Nov 18, 2020

    @JelleZijlstra
    Member

    Sounds like we update the inferred local type of val too soon. Hopefully this shouldn't be hard to fix.

  4. NiklasRosenstein commented on Jun 4, 2021

    @NiklasRosenstein
    Author

    I just hit this again in a different scenario.

    from dataclasses import dataclass
    
    class A:
      pass
    
    @dataclass
    class B(A):
      a: A
      v: int
    
    x: A = B(A(), 1)
    
    v: int = 0
    if isinstance(x, B):
      x, v = x.a, x.v  # error: "A" has no attribute "v"
    
    print(x, v)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions