"INTERNAL_ERROR": generic fun w/ Callable param w/ constrained return type followed by `*args` typed as `*Tuple[int, float]` crashes mypy
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 70/100
Hướng nghiên cứu
Tái hiện lỗi crash bằng crash_example.py của issue, sử dụng mypy 2.3.1 hoặc bản build phát triển. Bắt đầu trong mypy/checker.py và lần theo lệnh gọi đến mypy/types_utils.py, nơi traceback hiển thị IndexError. Hoàn thành khi tổ hợp hợp lệ này gồm một tham số callable bị ràng buộc và *args được unpack không còn gây crash; thêm coverage hồi quy nếu các bài kiểm thử hiện có của dự án cung cấp một vị trí phù hợp.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Crash Report
- Create crash_example.py as follows:
from typing import *
# mypy latest from master branch crashes (mypy 2.4.0+dev.b974556f84bd4ff5280b66bce1413fa942d1261e) (and earlier prod releases as well)
def generic_fun[
TypeVarWithConstraints: (str, bytes),
](
a: Callable[..., TypeVarWithConstraints],
*args: *Tuple[int, float]
): pass
- run mypy 2.3.1 or latest master on Github (2.4.0+dev) and observe a crash with "INTERNAL_ERROR":
[liveuser@localhost-live ~]$ mypy crash_example.py --show-traceback
crash_example.py:4: 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: 2.4.0+dev.b974556f84bd4ff5280b66bce1413fa942d1261e
[--show-traceback output is included further down]
Traceback
Traceback (most recent call last):
File "/home/liveuser/.local/bin/mypy", line 8, in <module>
sys.exit(console_entry())
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/__main__.py", line 16, in console_entry
main()
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/main.py", line 154, in main
res, messages, blockers = run_build(sources, options, fscache, t0, stdout, stderr)
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/main.py", line 244, in run_build
res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/build.py", line 422, in build
result = build_inner(
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/build.py", line 537, in build_inner
graph = dispatch(sources, manager, stdout, connect_threads)
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/build.py", line 4150, in dispatch
process_graph(graph, manager)
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/build.py", line 4618, in process_graph
done, still_working, results = manager.wait_for_done(graph)
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/build.py", line 1484, in wait_for_done
process_stale_scc(graph, next_scc, self)
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/build.py", line 4793, in process_stale_scc
graph[id].type_check_first_pass()
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/build.py", line 3410, in type_check_first_pass
self.type_checker().check_first_pass(recurse_into_functions=recurse_into_functions)
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/checker.py", line 632, in check_first_pass
self.accept(d)
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/checker.py", line 779, in accept
stmt.accept(self)
~~~~~~~~~~~^^^^^^
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/nodes.py", line 1165, in accept
return visitor.visit_func_def(self)
~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/checker.py", line 1346, in visit_func_def
self.visit_func_def_impl(defn)
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/checker.py", line 1350, in visit_func_def_impl
self.check_func_item(defn, name=defn.name)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/checker.py", line 1383, in check_func_item
self.check_func_def(defn, typ, name, allow_empty)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/checker.py", line 1514, in check_func_def
store_argument_type(item, i, typ, self.named_generic_type)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/liveuser/.local/lib/python3.13/site-packages/mypy/types_utils.py", line 183, in store_argument_type
defn.arguments[i].variable.type = arg_type
~~~~~~~~~~~~~~^^^
IndexError: list index out of range
crash_example.py:4: note: use --pdb to drop into pdb
Context/motivation
In PEP-0646 ( https://peps.python.org/pep-0646/ ), it is shown how an unpacked Tuple can be used to specify the type of *args:
# example from PEP-0646
def foo(*args: *Tuple[int, str]) -> None: pass
foo(1, "hello") # OK
In https://docs.python.org/3.13/reference/compound_stmts.html#type-parameter-lists
(separate from the SyntaxError in their overly_generic example which I have reported to the python team and am working with them to fix),
saying
A parenthesized tuple of expressions after the colon indicates a set of constraints (e.g. T: (str, bytes)). Each member of the tuple should be a type (again, this is not enforced at runtime). Constrained type variables can only take on one of the types in the list of constraints.
e.g.
from typing import *
def generic_fun_takes_a_callable_that_returns_either_str_or_bytes[
TypeVarWithConstraints: (str, bytes),
](a: Callable[..., TypeVarWithConstraints]):
pass
def some_fun_returns_str() -> str:
return 'abc'
def some_fun_returns_bytes() -> bytes:
return b'abc'
def some_fun_returns_int() -> int:
return 1
generic_fun_takes_a_callable_that_returns_either_str_or_bytes(some_fun_returns_str) # ok
generic_fun_takes_a_callable_that_returns_either_str_or_bytes(some_fun_returns_bytes) # ok
# not ok:
# error: Value of type variable "TypeVarWithConstraints" of "generic_fun_takes_a_callable_that_returns_either_str_or_bytes" cannot be "int" [type-var]
# generic_fun_takes_a_callable_that_returns_either_str_or_bytes(some_fun_returns_int)
So given
def generic_fun_takes_a_callable_that_returns_either_str_or_bytes[
TypeVarWithConstraints: (str, bytes),
](a: Callable[..., TypeVarWithConstraints]):
pass
is ok and
# example from PEP-0646
def foo(*args: *Tuple[int, str]) -> None: pass
is ok,
what about a function that has the arguments of the 1st followed by the arguments of the 2nd example, which both work fine with mypy on their own? (note PEP-0646 gives examples of *args being typed by an unpacked tuple even when preceded by other arguments)
def generic_fun[
TypeVarWithConstraints: (str, bytes),
](
a: Callable[..., TypeVarWithConstraints],
*args: *Tuple[int, float]
): pass
It turns out that the above crashes mypy unexpectedly in a way that causes the problem to tell me to file a bug, so I am doing so (see traceback towards top of ticket).
Your Environment
- Fedora Linux 42
- mypy 2.3.1 and mypy 2.4.0+dev.b974556f84bd4ff5280b66bce1413fa942d1261e
- python 3.13.2 in this case
Thanks very much!
- Ngôn ngữ chính
- Python
- Star
- 20.6k
- Fork
- 3.3k
- Merge trung bình
- 1 ngày 18 giờ
- Pull request đã merge (30 ngày)
- 54
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của python/mypy
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
-
documentation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
-
bug topic-configuration topic-error-reporting
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
qgis/QGIS-Documentation#11275 ·
-
bug priority:normal ready-for-dev
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
OpenHands/extensions#626 · 1 bình luận ·
-
Change observation tooltip text Đang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 90/100
CSCfi/sd-search-api#39 ·
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 90/100
-
please add to porn list Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
StevenBlack/hosts#3255 ·