Reject Self in PEP 695 type parameter bounds - #21961
Conversation
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
|
hmm...I think the ai description sounds plausible. But, b1f235a is prefixed |
| analyzed = self.anal_type( | ||
| value, | ||
| allow_placeholder=True, | ||
| prohibit_self_type="a type parameter constraint", |
There was a problem hiding this comment.
I think mypy already rejects Self in constraints. Why is this needed, would you elaborate?
There was a problem hiding this comment.
I think mypy already rejects Self in constraints. Why is this needed, would you elaborate?
class Foo:
# TypeVar constraint type cannot be parametrized by type variables
def constrained[T: (Foo, Self)](self: T) -> None: pass|
I don't know if there's a human behind this, but either way I've got a fix for this, just in case! |
PEP 673 lists the valid locations for Self, and a PEP 695 type
parameter bound is not one of them. mypy accepted it silently:
class C:
def bounded[T: Self](self: T) -> None: ...
reported no error at all. Analysing the bound with
prohibit_self_type gives the same message mypy already uses for the
other invalid locations.
The constraint case is also covered. mypy already rejected it, but
as "TypeVar constraint type cannot be parametrized by type
variables", which names the wrong reason.
b1f235a to
fe2e1f5
Compare
|
Both fair questions. Taking the second one first, because it decides what is You are right about constraints. I checked it rather than argued it. On the where from typing import Self
class C:
def bounded[T: Self](self: T) -> None: ...
def constrained[T: (C, Self)](self: T) -> None: ...Line 5 is your case and it already errors. Line 4 is the bound, and the base So the constraint hunk does not add coverage. It changes an existing message On the And to answer the question you were careful enough to ask out loud: the patch |
|
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
|
I am more leaning towards this being closed. May be the issue was not very clear because I think this is not exactly about lexical positions. from typing import Self
class C:
def foo[T: Self](self: T) -> None: passIsn't Self in a valid location(PEP 695)? |
Three gaps, all from issue #84 and #57: - provenance recorded a --head ref and never read it, so a squashed and force-pushed branch (python/mypy#21961) got permalinks to commits no branch had. It now reads the branch tip and refuses when the workspace disagrees. - nothing after handoff required provenance, so a filed PR was absent from mailman contributions entirely. hunt record-filing now writes it, and contributions exits non-zero listing any ready submission without one. - author_violations read the author and committer fields but not the Co-authored-by trailer, which publishes an address the same way. Also adds the resume-review budget coverage #81 asked for. The cumulative deadline, the clamped agent calls and the recorded override were already in place; nothing proved they survived a second invocation. Closes #84 Closes #57 Closes #81 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
You are right, and I checked it rather than argued it. Before I saw #21967 I prototyped your framing on the base commit class D[U]:
def g[T: U](self, x: T) -> None: ... # base: no error at allThat one has nothing to do with class F:
def nested[T: list[Self]](self, x: T) -> None: ... # base: no errorThe typing spec puts the rule under generics, not under
So Closing in favour of #21967. The probe notes are in a comment there. |
Closes #21960.
Mypy accepts
Selfas the bound of a PEP 695 type parameter, even thoughSelfis only valid in the locations defined by PEP 673. The same path alsofails to apply the existing
Selfvalidation consistently to constraints.The cause was that PEP 695 bounds and constraints were analyzed without the
existing
prohibit_self_typecontext. The fix passes the appropriateprohibition context through both paths and adds regression coverage to the
existing invalid-
Selftest case.How this was tested
At the reported base commit
ae39cdb2fba8908eeff6ec8d6b88879c62495fcc, themachine-checked reproduction accepted the invalid bound with
mypy_exit=0anddiagnostics=0. After the change, the final independentverification selected the focused test case and reported
2 passed, 8225 deselected.The checks ran on Windows 11. Mailman recorded Python 3.14.3 for the host
command metadata; the target test environment used Python 3.12.14. Provider
integration testing was not part of this focused type-checker regression.
An alternative not taken
The error could have been added as a special case at each PEP 695 analysis
call site. Reusing the existing
prohibit_self_typecontext keeps bound,constraint, nested, and
typing_extensions.Selfhandling on one validationpath and avoids duplicate diagnostics logic.
AI disclosure
This change was drafted with AI assistance: codex (
gpt-5.6-luna) wrote thepatch and codex (
gpt-5.6-luna) reviewed it under Mailman. The test resultsabove were executed by the Mailman harness. Human review and filing remain
pending.