Skip to content

Conversation

@sharkdp
Copy link
Contributor

@sharkdp sharkdp commented Oct 23, 2025

Summary

For final classes, we simplify Self to an instance of the class.

Ideally, we would also do that for other type variables with a final bound, but those seem like a rare edge-case, because there's not really any benefit to using a type variable in the first place, if it's bound to a final type (thank you, @AlexWaygood).

closes astral-sh/ty#1404

Test Plan

Added regression test

@sharkdp sharkdp added bug Something isn't working ty Multi-file analysis & type inference ecosystem-analyzer labels Oct 23, 2025
@github-actions
Copy link
Contributor

Diagnostic diff on typing conformance tests

No changes detected when running ty on typing conformance tests ✅

@github-actions
Copy link
Contributor

mypy_primer results

Changes were detected when running on open source projects
mitmproxy (https://github.com/mitmproxy/mitmproxy)
- mitmproxy/proxy/layers/http/_events.py:127:17: error[type-assertion-failure] Argument does not have asserted type `Never`
- Found 1886 diagnostics
+ Found 1885 diagnostics

sphinx (https://github.com/sphinx-doc/sphinx)
+ sphinx/util/osutil.py:84:10: error[invalid-argument-type] Argument to bound method `stat` is incorrect: Expected `Bottom[DirEntry[Unknown]]`, found `Top[DirEntry[Unknown]]`
+ sphinx/util/osutil.py:91:10: error[invalid-argument-type] Argument to bound method `stat` is incorrect: Expected `Bottom[DirEntry[Unknown]]`, found `Top[DirEntry[Unknown]]`
- Found 531 diagnostics
+ Found 533 diagnostics

antidote (https://github.com/Finistere/antidote)
- src/antidote/core/_catalog.py:214:65: error[invalid-argument-type] Argument is incorrect: Expected `ReferenceType[CatalogImpl]`, found `ReferenceType[Self@__init__]`
- Found 307 diagnostics
+ Found 306 diagnostics

scikit-learn (https://github.com/scikit-learn/scikit-learn)
- sklearn/preprocessing/_data.py:3422:31: error[no-matching-overload] No overload matches arguments
- sklearn/preprocessing/_data.py:3455:27: error[no-matching-overload] No overload matches arguments
- sklearn/preprocessing/_data.py:3506:31: error[no-matching-overload] No overload matches arguments
- Found 2477 diagnostics
+ Found 2474 diagnostics

jax (https://github.com/google/jax)
- jax/_src/pallas/mosaic_gpu/core.py:1478:24: error[invalid-return-type] Function can implicitly return `None`, which is not assignable to return type `TMEMLayout`
- Found 2476 diagnostics
+ Found 2475 diagnostics
Memory usage changes were detected when running on open source projects
trio (https://github.com/python-trio/trio)
-     memo metadata = ~30MB
+     memo metadata = ~28MB

@github-actions
Copy link
Contributor

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-argument-type 2 1 0
no-matching-overload 0 3 0
invalid-return-type 0 1 0
type-assertion-failure 0 1 0
Total 2 6 0

Full report with detailed diff (timing results)

@codspeed-hq
Copy link

codspeed-hq bot commented Oct 23, 2025

CodSpeed Performance Report

Merging #21042 will degrade performances by 5.41%

Comparing david/self-for-final-classes (5a6bfca) with main (e92fd51)

Summary

❌ 1 regression
✅ 20 untouched
⏩ 30 skipped1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Benchmarks breakdown

Mode Benchmark BASE HEAD Change
Simulation ty_micro[many_tuple_assignments] 61.3 ms 64.8 ms -5.41%

Footnotes

  1. 30 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@sharkdp sharkdp marked this pull request as ready for review October 23, 2025 09:49
Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

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

Thinking about this some more, I'm not totally sure this is sound for generic methods. Just because an instance type comes from a @final class doesn't mean that there aren't subtypes of that instance type, and the Self type variable could be solved to be one of those subtypes. For example:

import enum
from typing import Self

class F(enum.Enum):
    X = 0
    Y = 1

    def method(self) -> Self:
        return self

reveal_type(F.X.method())  # `Literal[F.X]` on `main`, `F` on this branch

@sharkdp sharkdp marked this pull request as draft October 23, 2025 10:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working ecosystem-analyzer ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Failed exhaustiveness matching on type variable

2 participants