Skip to content

Reject type variable whose upper bound is Self - #21967

Open
EmmanuelNiyonshuti wants to merge 1 commit into
python:masterfrom
EmmanuelNiyonshuti:typevar-bound-self-type
Open

Reject type variable whose upper bound is Self#21967
EmmanuelNiyonshuti wants to merge 1 commit into
python:masterfrom
EmmanuelNiyonshuti:typevar-bound-self-type

Conversation

@EmmanuelNiyonshuti

Copy link
Copy Markdown
Contributor

Fixes #21960

First attempt by an ai agent, See: #21961

Comment thread mypy/semanal.py
fullname = self.qualified_name(type_param.name)
if type_param.upper_bound:
upper_bound = self.anal_type(type_param.upper_bound, allow_placeholder=True)
# TODO: we should validate the upper bound is valid for a given kind.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m not entirely sure if this is the kind of validity that this comment is referring to.

@wolfgang-aura

Copy link
Copy Markdown

I filed #21961 for this issue with the narrower Self-location framing. Yours
is the right shape. I built the same check independently before I saw this PR
and it agrees line for line, so I am closing mine. Two things from running it.

The check covers more than Self, and that extra coverage is untested here. On
the base commit both of these are silently accepted, and with your patch both
error:

class D[U]:
    def g[T: U](self, x: T) -> None: ...

class F:
    def nested[T: list[Self]](self, x: T) -> None: ...

The first is the plain "bound parametrized by a type variable" case the spec
forbids, with no Self in it. A test case for it would pin the rule rather
than the symptom.

On fallout: with the check applied to ae39cdb, pytest mypy/test/testcheck.py was 8241 passed, 15 skipped, 7 xfailed, so no existing
test relies on a generic bound.

Minor: TYPE_VAR_GENERIC_BOUND_TYPE reads "can not be parametrized", while its
neighbour TYPE_VAR_GENERIC_CONSTRAINT_TYPE reads "cannot be parametrized".
Worth matching.

@github-actions

Copy link
Copy Markdown
Contributor

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

wolfgang-aura added a commit to wolfgang-aura/Mailman that referenced this pull request Sep 11, 2026
`mailman contributions --refresh` read only our own pull request's state.
python/mypy#21967 was opened against the issue python/mypy#21961 fixed and
the ledger said nothing for a day; it was found by hand in the PR thread.

While a pull request is open, the refresh now reads its issue's timeline,
where GitHub records every cross-reference, and keeps the other pull requests
from the same repository that are open or merged. The listing names each one,
says "no competing pull request" when the read was clean, and says why when it
could not be read, so an unchecked row never reads like an unchallenged one.
The command exits non-zero while a competitor exists.

The parser is tested against the recorded timeline of python/mypy#21960, which
holds ours, the competitor and a cross-repository reference to filter out.

Closes #86.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EmmanuelNiyonshuti

Copy link
Copy Markdown
Contributor Author

The repeated cross-linking and follow-up comments are making this a bit harder to follow than it needs to be. I also don't think the extra AI-generated activity is helping much here, especially given mypy's stance on LLM contributions from first-time contributors.
TLDR; I think the bot has had enough involvement in this one.

@wolfgang-aura

Copy link
Copy Markdown

Fair point, and sorry for the noise. The cross-posting and the long review comment were more than this thread needed, and posting them was my call. I'll step back and leave the PR to you and the maintainers.

wolfgang-aura added a commit to wolfgang-aura/Mailman that referenced this pull request Sep 11, 2026
…g reply

The comment that drew the complaint on python/mypy#21967 went out twelve
seconds before our own pull request closed, so a gate keyed on the close
could not have caught it. `handoff` now refuses an issue comment aimed at
a pull request another author opened, in any run state; `--closing-reply`
reaches only the superseding one, after provenance names it. A reply over
120 words gets a length warning in the block. The procedure says which
threads a filed run writes to, and in what order a close is recorded.

Follows #87.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Self is not rejected when used as a PEP 695 type parameter bound

2 participants