Skip to content

[1.16 regression] crashes on invalid and self-referential setter #19205

New issue

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

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

Already on GitHub? Sign in to your account

Closed
vfazio opened this issue Jun 2, 2025 · 4 comments · Fixed by #19208
Closed

[1.16 regression] crashes on invalid and self-referential setter #19205

vfazio opened this issue Jun 2, 2025 · 4 comments · Fixed by #19208

Comments

@vfazio
Copy link

vfazio commented Jun 2, 2025

Crash Report

(Tell us what happened.)

Traceback

xtf-py3.12vfazio@vfazio4 /mnt/development/xtf $ mypy --show-traceback simple.py 
simple.py:24: 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.17.0+dev.04afa499f936f671ee3f5a53edf3f5c8df18e76c
Traceback (most recent call last):
  File "/mnt/development/xtf/.venv/bin/mypy", line 8, in <module>
    sys.exit(console_entry())
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/__main__.py", line 15, in console_entry
    main()
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/main.py", line 127, in main
    res, messages, blockers = run_build(sources, options, fscache, t0, stdout, stderr)
  File "/mnt/development/xtf/.venv/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 "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/build.py", line 191, in build
    result = _build(
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/build.py", line 267, in _build
    graph = dispatch(sources, manager, stdout)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/build.py", line 2939, in dispatch
    process_graph(graph, manager)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/build.py", line 3337, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/build.py", line 3438, in process_stale_scc
    graph[id].type_check_first_pass()
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/build.py", line 2311, in type_check_first_pass
    self.type_checker().check_first_pass()
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 471, in check_first_pass
    self.accept(d)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 578, in accept
    stmt.accept(self)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/nodes.py", line 1216, in accept
    return visitor.visit_class_def(self)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 2542, in visit_class_def
    self.accept(defn.defs)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 578, in accept
    stmt.accept(self)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/nodes.py", line 1297, in accept
    return visitor.visit_block(self)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 3031, in visit_block
    self.accept(s)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 578, in accept
    stmt.accept(self)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/nodes.py", line 590, in accept
    return visitor.visit_overloaded_func_def(self)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 663, in visit_overloaded_func_def
    self._visit_overloaded_func_def(defn)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 682, in _visit_overloaded_func_def
    self.visit_decorator_inner(defn.items[1], skip_first_item=True)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 5249, in visit_decorator_inner
    self.check_func_item(e.func, name=e.func.name, allow_empty=allow_empty)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 1170, in check_func_item
    self.check_func_def(defn, typ, name, allow_empty)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 1457, in check_func_def
    self.accept(item.body)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 578, in accept
    stmt.accept(self)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/nodes.py", line 1297, in accept
    return visitor.visit_block(self)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 3031, in visit_block
    self.accept(s)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 578, in accept
    stmt.accept(self)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/nodes.py", line 1384, in accept
    return visitor.visit_assignment_stmt(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 3080, in visit_assignment_stmt
    self.check_assignment(s.lvalues[-1], s.rvalue, s.type is None, s.new_syntax)
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 3141, in check_assignment
    lvalue_type, index_lvalue, inferred = self.check_lvalue(lvalue, rvalue)
                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checker.py", line 4245, in check_lvalue
    lvalue_type = self.expr_checker.analyze_ordinary_member_access(lvalue, True, rvalue)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checkexpr.py", line 3333, in analyze_ordinary_member_access
    member_type = analyze_member_access(
                  ^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checkmember.py", line 226, in analyze_member_access
    result = _analyze_member_access(name, typ, mx, override_info)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checkmember.py", line 243, in _analyze_member_access
    return analyze_instance_member_access(name, typ, mx, override_info)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checkmember.py", line 350, in analyze_instance_member_access
    return analyze_var(name, getter.var, typ, mx)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checkmember.py", line 925, in analyze_var
    item = expand_and_bind_callable(p_ct, var, itype, name, mx, is_trivial_self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/development/xtf/.venv/lib/python3.12/site-packages/mypy/checkmember.py", line 984, in expand_and_bind_callable
    return expanded.arg_types[0]
           ~~~~~~~~~~~~~~~~~~^^^
IndexError: list index out of range
simple.py:24: : note: use --pdb to drop into pdb

To Reproduce

(Write what you did to reproduce the crash. Full source code is
appreciated. We also very much appreciate it if you try to narrow the
source down to a small stand-alone example.)

from typing import TYPE_CHECKING, Any, ClassVar, TypeVar

class NoopPowerResource:
    _hardware_type = None

    @property
    def hardware_type(self) -> Any:
        return self._hardware_type

    @hardware_type.setter
    def hardware_type(self) -> None:
        self.hardware_type = None

Your Environment

  • Mypy version used: 1.16.0 + 1.17.0+dev.04afa499f936f671ee3f5a53edf3f5c8df18e76c
  • Mypy command-line flags:
  • Mypy configuration options from mypy.ini (and other config files):
  • Python version used: CPython 3.12.4
  • Operating system and version: Ubuntu 22.04
@vfazio vfazio added the crash label Jun 2, 2025
@vfazio
Copy link
Author

vfazio commented Jun 2, 2025

This did not crash in 1.15 and prior.

xtf-py3.12vfazio@vfazio4 /mnt/development/xtf $ pip install mypy==1.15.0
...
Successfully installed mypy-1.15.0

[notice] A new release of pip is available: 25.0.1 -> 25.1.1
[notice] To update, run: pip install --upgrade pip
xtf-py3.12vfazio@vfazio4 /mnt/development/xtf $ mypy --show-traceback simple.py 
Success: no issues found in 1 source file

While it's definitely a bug in our code as we should be taking a value argument, I also wouldn't expect mypy to crash.

I'm going to venture a guess this was introduced as part of the property rework: #18510

@vfazio vfazio changed the title mypy crashses when property setter doesn't take an argument 1.16.0+ crashses when property setter doesn't take an argument Jun 2, 2025
@vfazio vfazio changed the title 1.16.0+ crashses when property setter doesn't take an argument 1.16.0+ crashes when property setter doesn't take an argument Jun 2, 2025
@JukkaL
Copy link
Collaborator

JukkaL commented Jun 2, 2025

I bisected this, and the regression was in #18774.

cc @ilevkivskyi as the author of the PR

@JukkaL JukkaL changed the title 1.16.0+ crashes when property setter doesn't take an argument [1.16. regerssopm0+ crashes when property setter doesn't take an argument Jun 2, 2025
@JukkaL JukkaL changed the title [1.16. regerssopm0+ crashes when property setter doesn't take an argument [1.16 regression] crashes when property setter doesn't take an argument Jun 2, 2025
@ilevkivskyi
Copy link
Member

ilevkivskyi commented Jun 2, 2025

OK, so the problem is not the invalid setter, the problem is that you are missing an underscore inside the setter body (thus creating an infinite recursion at runtime). This code doesn't crash and gives a correct error:

class NoopPowerResource:
    _hardware_type = None

    @property
    def hardware_type(self) -> Any:
        return self._hardware_type

    @hardware_type.setter
    def hardware_type(self) -> None:  # error: Invalid property setter signature  [misc]
        self._hardware_type = None

    def test(self) -> None:
        self.hardware_type = None

This happens because we "patch up" invalid properties after we analyze the property definition. Should be a simple fix.

@ilevkivskyi ilevkivskyi changed the title [1.16 regression] crashes when property setter doesn't take an argument [1.16 regression] crashes on invalid and self-referential setter Jun 2, 2025
@vfazio
Copy link
Author

vfazio commented Jun 2, 2025

Thanks for looking into it so quickly. I maybe simplified the original code too much to obscure the fact that in our scenario the attribute is a ClassVar.

I made some assumptions since the following did not crash:

from dataclasses import dataclass

from typing import Any, ClassVar, TypeVar, Generic

DT = TypeVar("DT", bound="Driver")
class Driver(Generic[DT]): pass


@dataclass
class Resource:
    hardware_type: ClassVar[type[Driver] | None] = Driver
    name: str

class NoopPowerResource(Resource):
    _hardware_type = None

    @property
    def hardware_type(self) -> Any:
        return self._hardware_type

    @hardware_type.setter
    def hardware_type(self, _value: Any) -> None:
        self.hardware_type = None

    async def on(self) -> None:
        pass

    async def off(self) -> None:
        pass

None of this changes the fact our code is still wrong, so I'm glad it was at least catching something

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants