Repository navigation
Mypy crashes on async tuple to tuple assignment #19920
Copy link
Copy link
Labels
Description
Crash Report
We got a tuple to tuple assignment with asyncio.gather, which crashes mypy, it looks like this:
tab_content: PriceCombinedDBAccessTabContentDto
price_region_stats: PriceRegionStats
( # < Error points to this line, this is line 70
price_data,
tab_content,
all_price_regions,
all_prof_role_groups,
price_region_stats,
has_civ_service,
) = await asyncio.gather(
get_price_data(handler, TabName.COMBINED_DBACCESS, price_description, backoffice_employer_id, session),
get_price_tab_content(http_client, config, TabName.COMBINED_DBACCESS, backoffice_employer_id),
get_all_price_regions(handler),
get_all_prof_role_groups(handler),
get_price_regions_stats(http_client, config),
check_employer_has_service_no_handler(
http_client, config, employer_id_or_backoffice_employer_id, ProductItemCode.ContactsView
),
)Traceback
xhh/pages/price/combined_dbaccess.py:70: 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.354bea6352ee7a38b05e2f42c874e7d1f7bf557a
Traceback (most recent call last):
File "/Users/gooverdian/Projects/xhh/.venv/bin/mypy", line 8, in <module>
sys.exit(console_entry())
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/__main__.py", line 15, in console_entry
main()
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/main.py", line 127, in main
res, messages, blockers = run_build(sources, options, fscache, t0, stdout, stderr)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/main.py", line 211, in run_build
res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/build.py", line 196, in build
result = _build(
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/build.py", line 272, in _build
graph = dispatch(sources, manager, stdout)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/build.py", line 2946, in dispatch
process_graph(graph, manager)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/build.py", line 3346, in process_graph
process_stale_scc(graph, scc, manager)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/build.py", line 3447, in process_stale_scc
graph[id].type_check_first_pass()
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/build.py", line 2325, in type_check_first_pass
self.type_checker().check_first_pass()
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 524, in check_first_pass
self.accept(d)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 635, in accept
stmt.accept(self)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/nodes.py", line 1127, in accept
return visitor.visit_decorator(self)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 5412, in visit_decorator
self.visit_decorator_inner(e)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 5419, in visit_decorator_inner
self.check_func_item(e.func, name=e.func.name, allow_empty=allow_empty)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 1231, in check_func_item
self.check_func_def(defn, typ, name, allow_empty)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 1504, in check_func_def
self.accept(item.body)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 635, in accept
stmt.accept(self)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/nodes.py", line 1542, in accept
return visitor.visit_block(self)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 3126, in visit_block
self.accept(s)
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 635, in accept
stmt.accept(self)
~~~~~~~~~~~^^^^^^
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/nodes.py", line 1629, in accept
return visitor.visit_assignment_stmt(self)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 3177, in visit_assignment_stmt
self.check_assignment(s.lvalues[-1], s.rvalue, s.type is None, s.new_syntax)
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 3233, in check_assignment
self.check_assignment_to_multiple_lvalues(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
lvalue.items, rvalue, rvalue, infer_lvalue_type
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 3984, in check_assignment_to_multiple_lvalues
self.check_multi_assignment(lvalues, rvalue, context, infer_lvalue_type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 4062, in check_multi_assignment
self.check_multi_assignment_from_tuple(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
lvalues, rvalue, rvalue_type, context, undefined_rvalue, infer_lvalue_type
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/Users/gooverdian/Projects/xhh/.venv/lib/python3.13/site-packages/mypy/checker.py", line 4202, in check_multi_assignment_from_tuple
assert isinstance(reinferred_rvalue_type, TupleType)
~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: To Reproduce
This file is not new, so the diff, which lead to that error is adding types to some members of a left tuple before the assignment:
+ tab_content: PriceCombinedDBAccessTabContentDto
+ price_region_stats: PriceRegionStats
(
price_data,
tab_content,
all_price_regions,
all_prof_role_groups,
price_region_stats,
has_civ_service,
) = await asyncio.gather(
get_price_data(handler, TabName.COMBINED_DBACCESS, price_description, backoffice_employer_id, session),
get_price_tab_content(http_client, config, TabName.COMBINED_DBACCESS, backoffice_employer_id),
get_all_price_regions(handler),
get_all_prof_role_groups(handler),
get_price_regions_stats(http_client, config),
check_employer_has_service_no_handler(
http_client, config, employer_id_or_backoffice_employer_id, ProductItemCode.ContactsView
),
)UPD: Found a way to reproduce it in playground https://mypy-play.net/?mypy=latest&python=3.13&gist=ca818b7f434ca646dd6373b26f5b58f6, seems like there would be an error if it wouldn't crash.
Your Environment
- Mypy version used: 1.15.0, 1.18.2, git master
- Mypy command-line flags: --config-file (path to config), --show-traceback, (path to file)
- Mypy configuration options from
mypy.ini(and other config files):[tool.mypy] warn_redundant_casts = true warn_unused_ignores = true warn_unused_configs = true show_error_codes = true ignore_missing_imports = true follow_imports = "silent" follow_untyped_imports = true disallow_untyped_calls = false disallow_incomplete_defs = true disallow_untyped_decorators = true check_untyped_defs = true strict = true disallow_untyped_defs = true disallow_any_generics = true disallow_subclassing_any = true warn_return_any = true enable_error_code = [ "deprecated", "ignore-without-code", ] python_version = "3.13" exclude = [ "xhh/pages/employer/documents-management", "xhh/pages/employer/financial-documents", "xhh/pages/employer/reviews-settings", "xhh/page.py", ] - Python version used: 3.13
- Operating system and version: mac sequoia 15.6.1, alpine ubuntu (docker)
Reactions are currently unavailable
Activity
gooverdian commentedon Sep 24, 2025
I was playing with this for a bit, seems like changing it to list solves the problem:
Didn't manage to reproduce this bug on mypy-play though sadlyGot it! https://mypy-play.net/?mypy=latest&python=3.13&gist=ca818b7f434ca646dd6373b26f5b58f6sterliakov commentedon Sep 24, 2025
This still repro's on master and does not really need
asyncio(and even async/await at all!). mypy 1.0.0 also crashes on this snippet.The following is enough to trigger the crash (or playground):
This happens when all following conditions hold true:
ilevkivskyi commentedon Sep 27, 2025
@sterliakov I think simply removing the assert as you do in your PR in wrong. I think outer type context should never affect overload selection, since in Python overload selection happens at runtime, and we must respect this semantics. We still can (and should) use the outer context while type-checking the call to selected overload.
This however may be a bigger change (with potential performance implications), so we need to be careful, but FWIW I think this is the right thing to do. Also cc @JukkaL for visibility.
sterliakov commentedon Sep 27, 2025
ilevkivskyi commentedon Sep 27, 2025
@sterliakov
Completely ignoring outer context in
infer_overload_return_type()(a two line change that also fixes this crash) causes only 5 tests to fail, out of those:And in all 5 cases using the context during checking, but not during selection would fix the errors. This part is however tricky without a major performance penalty.
So I would not be so dramatic. However, as I said before, this is something that requires care.
Merge remote-tracking branch 'upstream/master' into bugfix/pythongh-1…
Merge branch 'master' into bugfix/pythongh-19920-tuple-inference-crash
Fix crash when unpacking return value from overload (#21830)
Fix crash when unpacking return value from overload (#21830)