Skip to content

Crash if a class is generic over a PEP-695 parameter that has the same name as an old-style TypeVar that is also in scope and the old-style TypeVar has a bound which uses an unquoted forward reference #18507

Closed

Description

@AlexWaygood

Crash Report

This feels quite specific, but I think it may come up a surprising amount as more and more people use codemods to try to auto-upgrade their code to use PEP 695 in the coming years! Mypy crashes on this snippet:

from typing import TypeVar

T = TypeVar("T", bound=Foo)

class Foo: ...
class Bar[T]: ...

The following things must all be true for the crash to occur:

  • The global-scope TypeVar must have the same name as the type parameter used for Bar
  • The global-scope TypeVar must have a bound= argument that uses a forward reference
  • The forward reference in the global-scope TypeVar's bound must be unquoted. (For .py files, you generally need to quote all forward references, but this is not true for stubs.)

Traceback

% mypy foo.py --python-version=3.12 --show-traceback
foo.py:6: 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.15.0+dev.58de753b6b76227ff726e9ce1888cfc24c7ba44b
Traceback (most recent call last):
  File "/Users/alexw/dev/typeshed/.venv/bin/mypy", line 8, in <module>
    sys.exit(console_entry())
  File "/Users/alexw/dev/mypy/mypy/__main__.py", line 15, in console_entry
    main()
  File "/Users/alexw/dev/mypy/mypy/main.py", line 119, in main
    res, messages, blockers = run_build(sources, options, fscache, t0, stdout, stderr)
  File "/Users/alexw/dev/mypy/mypy/main.py", line 203, in run_build
    res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
  File "/Users/alexw/dev/mypy/mypy/build.py", line 191, in build
    result = _build(
  File "/Users/alexw/dev/mypy/mypy/build.py", line 267, in _build
    graph = dispatch(sources, manager, stdout)
  File "/Users/alexw/dev/mypy/mypy/build.py", line 2937, in dispatch
    process_graph(graph, manager)
  File "/Users/alexw/dev/mypy/mypy/build.py", line 3335, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/Users/alexw/dev/mypy/mypy/build.py", line 3430, in process_stale_scc
    mypy.semanal_main.semantic_analysis_for_scc(graph, scc, manager.errors)
  File "/Users/alexw/dev/mypy/mypy/semanal_main.py", line 93, in semantic_analysis_for_scc
    process_top_levels(graph, scc, patches)
  File "/Users/alexw/dev/mypy/mypy/semanal_main.py", line 220, in process_top_levels
    deferred, incomplete, progress = semantic_analyze_target(
  File "/Users/alexw/dev/mypy/mypy/semanal_main.py", line 351, in semantic_analyze_target
    analyzer.refresh_partial(
  File "/Users/alexw/dev/mypy/mypy/semanal.py", line 646, in refresh_partial
    self.refresh_top_level(node)
  File "/Users/alexw/dev/mypy/mypy/semanal.py", line 657, in refresh_top_level
    self.accept(d)
  File "/Users/alexw/dev/mypy/mypy/semanal.py", line 7241, in accept
    node.accept(self)
    ~~~~~~~~~~~^^^^^^
  File "/Users/alexw/dev/mypy/mypy/nodes.py", line 1177, in accept
    return visitor.visit_class_def(self)
           ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/Users/alexw/dev/mypy/mypy/semanal.py", line 1728, in visit_class_def
    self.analyze_class(defn)
    ~~~~~~~~~~~~~~~~~~^^^^^^
  File "/Users/alexw/dev/mypy/mypy/semanal.py", line 1869, in analyze_class
    bases, tvar_defs, is_protocol = self.clean_up_bases_and_infer_type_variables(
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        defn, bases, context=defn
        ^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/Users/alexw/dev/mypy/mypy/semanal.py", line 2174, in clean_up_bases_and_infer_type_variables
    assert isinstance(node.node, TypeVarLikeExpr)
           ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError:

To Reproduce

Paste the above snippet into a foo.py file and run mypy --python-version=3.12 foo.py --show-traceback

Your Environment

  • Mypy version used: 1.15.0+dev.58de753b6b76227ff726e9ce1888cfc24c7ba44b
  • Mypy command-line flags: --python-version=3.12 --show-traceback
  • Python version used: 3.13.1

Activity

  1. AlexWaygood commented on Jan 22, 2025

    @AlexWaygood
    MemberAuthor

    (Feel free to retitle the issue if you can think of something snappier...)

  2. added a commit that references this issue on Oct 20, 2025
    583c5f7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions