Skip to content
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

AssertionError: Must not defer during final iteration & TypeError: '<' not supported between instances of 'ArgKind' and 'ArgKind' #14329

Closed
CoolCat467 opened this issue Dec 21, 2022 · 0 comments · Fixed by #14508

Comments

@CoolCat467
Copy link

Crash Report

Basically, I am trying to program a game with the Trio asynchronous library. Using the mypy daemon and type checking different files makes it crash. Trying to make excerpt files for demonstrating the issue, I also found that I would encounter AssertionError: Must not defer during final iteration if I had the setup slightly different.

Traceback

If you type check main.py and then type check with_trio.py, you get this traceback from the log file:

/home/<my_username>/.local/lib/python3.11/site-packages/trio-stubs/__init__.pyi:285: 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: 0.991
/home/<my_username>/.local/lib/python3.11/site-packages/trio-stubs/__init__.pyi: 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: 0.991
Traceback (most recent call last):
  File "mypy/dmypy_server.py", line 229, in serve
  File "mypy/dmypy_server.py", line 274, in run_command
  File "mypy/dmypy_server.py", line 342, in cmd_run
  File "mypy/dmypy_server.py", line 411, in check
  File "mypy/dmypy_server.py", line 595, in fine_grained_increment_follow_imports
  File "mypy/server/update.py", line 263, in update
  File "mypy/server/update.py", line 365, in update_one
  File "mypy/server/update.py", line 427, in update_module
  File "mypy/server/update.py", line 650, in update_module_isolated
  File "mypy/semanal_main.py", line 85, in semantic_analysis_for_scc
  File "mypy/semanal_main.py", line 243, in process_functions
  File "mypy/semanal_main.py", line 282, in process_top_level_function
  File "mypy/semanal_main.py", line 339, in semantic_analyze_target
  File "mypy/semanal.py", line 581, in refresh_partial
  File "mypy/semanal.py", line 6049, in accept
  File "mypy/errors.py", line 1149, in report_internal_error
  File "mypy/semanal.py", line 6047, in accept
  File "mypy/nodes.py", line 822, in accept
  File "mypy/semanal.py", line 808, in visit_func_def
  File "mypy/semanal.py", line 837, in analyze_func_def
  File "mypy/typeanal.py", line 865, in visit_callable_type
  File "mypy/typeanal.py", line 1391, in anal_array
  File "mypy/typeanal.py", line 1400, in anal_type
  File "mypy/types.py", line 2738, in accept
  File "mypy/typeanal.py", line 1050, in visit_type_type
  File "mypy/typeanal.py", line 1400, in anal_type
  File "mypy/types.py", line 2172, in accept
  File "mypy/typeanal.py", line 979, in visit_tuple_type
  File "mypy/typeanal.py", line 1391, in anal_array
  File "mypy/typeanal.py", line 1400, in anal_type
  File "mypy/types.py", line 2782, in accept
  File "mypy/typeanal.py", line 1055, in visit_placeholder_type
  File "mypy/semanal.py", line 5724, in defer
AssertionError: Must not defer during final iteration

If you type check with_trio.py and then type check main.py, you get this traceback from the log file:

Traceback (most recent call last):
  File "mypy/dmypy_server.py", line 229, in serve
  File "mypy/dmypy_server.py", line 274, in run_command
  File "mypy/dmypy_server.py", line 342, in cmd_run
  File "mypy/dmypy_server.py", line 411, in check
  File "mypy/dmypy_server.py", line 659, in fine_grained_increment_follow_imports
  File "mypy/server/update.py", line 263, in update
  File "mypy/server/update.py", line 365, in update_one
  File "mypy/server/update.py", line 422, in update_module
  File "mypy/server/astdiff.py", line 205, in snapshot_symbol_table
  File "mypy/server/astdiff.py", line 278, in snapshot_definition
  File "mypy/server/astdiff.py", line 205, in snapshot_symbol_table
  File "mypy/server/astdiff.py", line 249, in snapshot_definition
  File "mypy/server/astdiff.py", line 294, in snapshot_optional_type
  File "mypy/server/astdiff.py", line 289, in snapshot_type
  File "mypy/types.py", line 1792, in accept
  File "mypy/server/astdiff.py", line 406, in visit_callable_type
  File "mypy/server/astdiff.py", line 300, in snapshot_types
  File "mypy/server/astdiff.py", line 289, in snapshot_type
  File "mypy/types.py", line 2592, in accept
  File "mypy/server/astdiff.py", line 447, in visit_union_type
TypeError: '<' not supported between instances of 'ArgKind' and 'ArgKind'

To Reproduce

With the following files in a folder with nothing else

In main.py:

import does_not_exist

In with_trio.py:

import trio

In recreate.sh:

#!/bin/bash
# -*- coding: utf-8 -*-

# "AssertionError: Must not defer during final iteration" one:
dmypy start -- --warn-unused-ignores --show-error-codes --show-traceback --strict --show-absolute-path --disallow-untyped-calls --no-warn-no-return --show-column-numbers --no-color-output --warn-redundant-casts --disallow-untyped-defs --no-implicit-reexport --warn-unreachable --no-error-summary
dmypy check main.py --export-types
dmypy check with_trio.py --export-types

# "TypeError: '<' not supported between instances of 'ArgKind' and 'ArgKind'" one:
dmypy start -- --warn-unused-ignores --show-error-codes --show-traceback --strict --show-absolute-path --disallow-untyped-calls --no-warn-no-return --show-column-numbers --no-color-output --warn-redundant-casts --disallow-untyped-defs --no-implicit-reexport --warn-unreachable --no-error-summary
dmypy check with_trio.py --export-types
dmypy check main.py --export-types

Assuming you don't already have a daemon running, Run recreate.sh. There are more than one dmypy start command because it crashes in-between the two setups.

Your Environment

trio==0.22.0
trio-typing==0.7.0

  • Mypy version used: 0.991
  • Mypy command-line flags: See listed recreate.sh file for all daemon flags
  • Mypy configuration options from mypy.ini (and other config files): No other configuration files
  • Python version used: Python 3.11.0rc1 (main, Aug 12 2022, 10:02:14) [GCC 11.2.0]
  • Operating system and version: 64 bit Linux Ubuntu Budgie 10.6.1 (Ubuntu 22.04.1 LTS)
JukkaL pushed a commit that referenced this issue Jan 22, 2023
Ref #14329

This fixes one of the crashes reported in the issue. In fact, using
recursive type caught this crash statically, plus another subtle crash
in `snapshot_optional_type()`, _without a single false positive_ (I was
able to cleanly type also symbol table snapshots, but decided it is not
worth the churn since we only ever compare them with `==`, supported by
~every Python object). I feel triumphant :-)
JukkaL pushed a commit that referenced this issue Jan 23, 2023
Fixes #14329

This fixes the second crash reported in the issue (other one is already
fixed). This one is tricky, it looks like it happens only when we bring
in a new import cycle in an incremental update with
`--follow-import=normal`. To explain the reason, a little reminder of
how semantic analyzer passes work:

* Originally, we recorded progress automatically when some new symbol
was resolved and added to symbol tables.
* With implementation of recursive types, this mechanism was
insufficient, as recursive types require modifying some symbols _in
place_, this is why `force_progress` flag was added to `defer()`.
* I was only careful with this flag for recursive type aliases (that
were implemented first), for other things (like recursive TypedDicts,
etc) I just always passed `force_progress=True` (without checking if we
actually resolved some placeholder types).
* The reasoning for that is if we ever add `becomes_typeinfo=True`,
there is no way this symbol will later be unresolved (otherwise how
would we know this is something that is a type).
* It turns out this reasoning doesn't work in some edge cases in daemon
mode, we do put some placeholders with `becomes_typeinfo=True` for
symbols imported from modules that were not yet processed, thus causing
a crash (see test cases).
* There were two options to fix this: one is to stop creating
placeholders with `becomes_typeinfo=True` for unimported symbols in
daemon mode, other one is to always carefully check if in-place update
of a symbol actually resulted in progress.
* Ultimately I decided that the first way is too fragile (and I don't
understand how import following works for daemon anyway), and the second
way is something that is technically correct anyway, so here is this PR

I didn't add test cases for each of the crash scenarios, since they are
all very similar. I only added two that I encountered "in the wild",
upper bound and tuple base caused actual crash in `trio` stubs, plus
also randomly a test for a TypedDict crash.

_EDIT:_ and one more thing, the "cannot resolve name" error should never
appear in normal mode, only in daemon update (see reasoning above), so I
don't make those error messages detailed, just add some minimal info if
we will need to debug them.
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.

2 participants