Skip to content

AssertionError when using reveal_type on a class-bound ParamSpec. #19839

@JBushagour

Description

@JBushagour

Crash Report

The following code triggers an AssertionError internally in mypy:

from collections.abc import Callable
from typing import reveal_type


class Sneaky[**P]:
    def __init__(self, fn: Callable[P, object], *args: P.args, **kwargs: P.kwargs) -> None:
        self.args = args
        self.kwargs = kwargs


def identity(x: int) -> int:
    return x

reveal_type(Sneaky(identity, 1).args)

Traceback

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/__main__.py", line 37, in <module>
    console_entry()
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/__main__.py", line 15, in console_entry
    main()
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/main.py", line 127, in main
    res, messages, blockers = run_build(sources, options, fscache, t0, stdout, stderr)
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/main.py", line 211, in run_build
    res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/build.py", line 197, in build
    result = _build(
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/build.py", line 273, in _build
    graph = dispatch(sources, manager, stdout)
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/build.py", line 2970, in dispatch
    process_graph(graph, manager)
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/build.py", line 3403, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/build.py", line 3504, in process_stale_scc
    graph[id].type_check_first_pass()
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/build.py", line 2344, in type_check_first_pass
    self.type_checker().check_first_pass()
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checker.py", line 524, in check_first_pass
    self.accept(d)
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checker.py", line 635, in accept
    stmt.accept(self)
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/nodes.py", line 1562, in accept
    return visitor.visit_expression_stmt(self)
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checker.py", line 4842, in visit_expression_stmt
    expr_type = self.expr_checker.accept(s.expr, allow_none_return=True, always_allow_any=True)
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checkexpr.py", line 6020, in accept
    typ = self.visit_call_expr(node, allow_none_return=True)
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checkexpr.py", line 493, in visit_call_expr
    return self.accept(e.analyzed, self.type_context[-1])
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checkexpr.py", line 6048, in accept
    typ = node.accept(self)
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/nodes.py", line 2520, in accept
    return visitor.visit_reveal_expr(self)
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checkexpr.py", line 4723, in visit_reveal_expr
    revealed_type = self.accept(
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checkexpr.py", line 6048, in accept
    typ = node.accept(self)
          ^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/nodes.py", line 2175, in accept
    return visitor.visit_member_expr(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checkexpr.py", line 3315, in visit_member_expr
    result = self.analyze_ordinary_member_access(e, is_lvalue)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checkexpr.py", line 3345, in analyze_ordinary_member_access
    member_type = analyze_member_access(
                  ^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checkmember.py", line 227, in analyze_member_access
    result = _analyze_member_access(name, typ, mx, override_info)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checkmember.py", line 244, in _analyze_member_access
    return analyze_instance_member_access(name, typ, mx, override_info)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checkmember.py", line 386, in analyze_instance_member_access
    return analyze_member_var_access(name, typ, info, mx)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checkmember.py", line 570, in analyze_member_var_access
    return analyze_var(name, v, itype, mx, implicit=implicit, is_trivial_self=is_trivial_self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checkmember.py", line 888, in analyze_var
    result = expand_without_binding(typ, var, itype, original_itype, mx)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/checkmember.py", line 955, in expand_without_binding
    expanded = expand_type_by_instance(typ, itype)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/expandtype.py", line 115, in expand_type_by_instance
    return expand_type(typ, variables)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/expandtype.py", line 70, in expand_type
    return typ.accept(ExpandTypeVisitor(env))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/types.py", line 823, in accept
    return visitor.visit_param_spec(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/mypy/expandtype.py", line 273, in visit_param_spec
    assert t.flavor == ParamSpecFlavor.BARE
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 
main.py:14: 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.19.0+dev.9ae3e9aa160c11b99960f12eef111e4a3197b7d3
main.py:14: : note: use --pdb to drop into pdb

To Reproduce

The above code should be sufficient; here's a mypy-play link for convenience.

AFAICT it's reproducible across all versions of mypy that support PEP 695 generics, including versions that require --enable-incomplete-feature=NewGenericSyntax (1.11.0 and up). Something of note is that mypy doesn't trigger the assertion if we define the ParamSpec explicitly with P = ParamSpec("P") (mypy-play link).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions