Skip to content

Binding a name that is used before but now out of scope in a pattern match breaks mypy #16793

@Luis-omega

Description

@Luis-omega

If you already used a name like value to define something in a branch of a match, like a function def value()... and by some reason you use the same name as a binding in another branch of the match case Some(value), then I guess that value is lookup for it's previous value (a function) instead of making a new fresh variable for it, this broke an assertion.


some.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: 1.9.0+dev.75b68fa2c0d32bd08b98b00aece20c22d82b1b15
Traceback (most recent call last):
  File "projects/mal/impls/python.3/.env/bin/mypy", line 8, in <module>
    sys.exit(console_entry())
  File "projects/mypy/mypy/__main__.py", line 15, in console_entry
    main()
  File "projects/mypy/mypy/main.py", line 100, in main
    res, messages, blockers = run_build(sources, options, fscache, t0, stdout, stderr)
  File "projects/mypy/mypy/main.py", line 182, in run_build
    res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
  File "projects/mypy/mypy/build.py", line 191, in build
    result = _build(
  File "projects/mypy/mypy/build.py", line 265, in _build
    graph = dispatch(sources, manager, stdout)
  File "projects/mypy/mypy/build.py", line 2941, in dispatch
    process_graph(graph, manager)
  File "projects/mypy/mypy/build.py", line 3339, in process_graph
    process_stale_scc(graph, scc, manager)
  File "projects/mypy/mypy/build.py", line 3440, in process_stale_scc
    graph[id].type_check_first_pass()
  File "projects/mypy/mypy/build.py", line 2309, in type_check_first_pass
    self.type_checker().check_first_pass()
  File "projects/mypy/mypy/checker.py", line 481, in check_first_pass
    self.accept(d)
  File "projects/mypy/mypy/checker.py", line 591, in accept
    stmt.accept(self)
  File "projects/mypy/mypy/nodes.py", line 787, in accept
    return visitor.visit_func_def(self)
  File "projects/mypy/mypy/checker.py", line 1001, in visit_func_def
    self._visit_func_def(defn)
  File "projects/mypy/mypy/checker.py", line 1005, in _visit_func_def
    self.check_func_item(defn, name=defn.name)
  File "projects/mypy/mypy/checker.py", line 1078, in check_func_item
    self.check_func_def(defn, typ, name, allow_empty)
  File "projects/mypy/mypy/checker.py", line 1294, in check_func_def
    self.accept(item.body)
  File "projects/mypy/mypy/checker.py", line 591, in accept
    stmt.accept(self)
  File "projects/mypy/mypy/nodes.py", line 1223, in accept
    return visitor.visit_block(self)
  File "projects/mypy/mypy/checker.py", line 2771, in visit_block
    self.accept(s)
  File "projects/mypy/mypy/checker.py", line 591, in accept
    stmt.accept(self)
  File "projects/mypy/mypy/nodes.py", line 1607, in accept
    return visitor.visit_match_stmt(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "projects/mypy/mypy/checker.py", line 5063, in visit_match_stmt
    inferred_types = self.infer_variable_types_from_type_maps(type_maps)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "projects/mypy/mypy/checker.py", line 5127, in infer_variable_types_from_type_maps
    assert isinstance(node, Var)
AssertionError: 
some.py:10: : note: use --pdb to drop into pdb

I was able to reduce the crash to this file:

from dataclasses import dataclass

@dataclass
class Some:
    value: int | "Some"

def some(x: Some):
    match x:
        case int():

            def value():
                return 1

        case Some(value):
            pass

I put a print in the function handling the match and got:

  NameExpr(x [l])
  Pattern(
    ClassPattern:11(
      NameExpr(int [builtins.int])))
  Body(
    FuncDef:13(
      value
      Block:14(
        ReturnStmt:14(
          IntExpr(1)))))
  Pattern(
    ClassPattern:16(
      NameExpr(Some [some.Some])
      Positionals(
        AsPattern:16(
          NameExpr(value [l])))))
  Body(
    PassStmt:17()))

The particular source of the crash is the

AsPattern:16(
          NameExpr(value [l])))))

A print of the value that breaks the assert just before breaking:

FuncDef:13(
  value
  Block:14(
    ReturnStmt:14(
      IntExpr(1))))
FuncDef:13(
  value
  Block:14(
    ReturnStmt:14(
      IntExpr(1))))
  • Mypy version used: both 1.7.something and 1.9.0+dev.75b68fa2c0d32bd08b98b00aece20c22d82b1b15
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.11.6
  • Operating system and version: Archlinux

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions