Skip to content

Crash on assigning to guarded variable in failed TypeGuard branch #10665

Closed
@p7g

Description

@p7g

The title is probably not fully accurate, but I'm unable to fully intuit what's going on.

Crash Report

I'm using a TypeGuard to narrow the type of a variable from a more general one (not Any). If I add a branch like if not guard(var): var = ... there's an AssertionError.

I suspect something weird happens to the type of the variable after the failed type guard.

Traceback

test4.py:10: error: INTERNAL ERROR -- Please try using mypy master on Github:                                                                                                                      
https://mypy.readthedocs.io/en/stable/common_issues.html#using-a-development-mypy-build
Please report a bug at https://github.com/python/mypy/issues                                                                                                                                       
version: 0.910+dev.7f54bd064399ee4e38586c311a2796ff3f255276
Traceback (most recent call last):
  File "/Users/patrick/.local/venvs/fellow/bin/mypy", line 8, in <module>
    sys.exit(console_entry())
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/__main__.py", line 11, in console_entry
    main(None, sys.stdout, sys.stderr)
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/main.py", line 103, in main
    res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/build.py", line 179, in build
    result = _build(
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/build.py", line 254, in _build
    graph = dispatch(sources, manager, stdout)
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/build.py", line 2696, in dispatch
    process_graph(graph, manager)
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/build.py", line 3020, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/build.py", line 3118, in process_stale_scc
    graph[id].type_check_first_pass()
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/build.py", line 2165, in type_check_first_pass
    self.type_checker().check_first_pass()
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/checker.py", line 294, in check_first_pass
    self.accept(d)
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/checker.py", line 401, in accept
    stmt.accept(self)
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/nodes.py", line 1208, in accept
    return visitor.visit_if_stmt(self)
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/checker.py", line 3276, in visit_if_stmt
    self.accept(s.else_body)
  File "/Users/patrick/.asdf/installs/python/3.8.8/lib/python3.8/contextlib.py", line 120, in __exit__
    next(self.gen)
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/binder.py", line 407, in frame_context
    self.pop_frame(can_skip, fall_through)
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/binder.py", line 229, in pop_frame
    self.last_pop_changed = self.update_from_options(options)
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/binder.py", line 205, in update_from_options
    type = join_simple(self.declarations[key], type, other)
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/join.py", line 142, in join_simple
    value = t.accept(TypeJoinVisitor(s))
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/types.py", line 290, in accept
    return visitor.visit_type_guard_type(self)
  File "/Users/patrick/.local/venvs/fellow/lib/python3.8/site-packages/mypy/join.py", line 436, in visit_type_guard_type
    assert False, "This should be never called, got {}".format(t)
AssertionError: This should be never called, got TypeGuard(test4.B)
test4.py:10: : note: use --pdb to drop into pdb

To Reproduce

Here's a repro:

from typing_extensions import TypeGuard

class A: pass
class B(A): pass

def guard(a: A) -> TypeGuard[B]:
	pass

a = A()
if not guard(a):
	a = A()

Note that the same error occurs if B is not a subclass of A, but then the code doesn't really make any sense.

Your Environment

  • Mypy version used: 0.902 and latest master
  • Mypy command-line flags: --show-traceback --config-file=empty.ini
  • Mypy configuration options from mypy.ini (and other config files): none (just the [mypy] header)
  • Python version used: 3.8.8
  • Operating system and version: macOS 11.2.3 (20D91)

For what it's worth, the actual code where I encountered the issue looks more like this:

class PayloadA(TypedDict):
    type: Literal["A"]
   
class PayloadB(TypedDict):
    type: Literal["B"]
    ...
    
Payload = Union[PayloadA, PayloadB]

def is_payload(raw_msg: Mapping[str, Any]) -> TypeGuard[Payload]:
    ...

class Client:
    ...

    def next_payload(self) -> Payload:
        msg = json.loads(self._next_payload())
        while not is_payload(msg):
            msg = json.loads(self._next_payload())
        return msg

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions