[ty] Use 'unknown' specialization for upper bound on Self (#20325)

## Summary

closes https://github.com/astral-sh/ty/issues/1156

## Test Plan

Added a regression test
This commit is contained in:
David Peter 2025-09-10 17:00:28 +02:00 committed by GitHub
parent 57d1f7132d
commit 65982a1e14
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 19 additions and 4 deletions

View file

@ -2,7 +2,7 @@
```toml ```toml
[environment] [environment]
python-version = "3.11" python-version = "3.13"
``` ```
`Self` is treated as if it were a `TypeVar` bound to the class it's being used on. `Self` is treated as if it were a `TypeVar` bound to the class it's being used on.
@ -147,6 +147,23 @@ class Shape:
return self return self
``` ```
## `Self` for classes with a default value for their generic parameter
This is a regression test for <https://github.com/astral-sh/ty/issues/1156>.
```py
from typing import Self
class Container[T = bytes]:
def __init__(self: Self, data: T | None = None) -> None:
self.data = data
reveal_type(Container()) # revealed: Container[bytes]
reveal_type(Container(1)) # revealed: Container[int]
reveal_type(Container("a")) # revealed: Container[str]
reveal_type(Container(b"a")) # revealed: Container[bytes]
```
## Invalid Usage ## Invalid Usage
`Self` cannot be used in the signature of a function or variable. `Self` cannot be used in the signature of a function or variable.

View file

@ -5711,9 +5711,7 @@ impl<'db> Type<'db> {
], ],
}); });
}; };
let instance = Type::ClassLiteral(class).to_instance(db).expect( let instance = Type::instance(db, class.unknown_specialization(db));
"nearest_enclosing_class must return type that can be instantiated",
);
let class_definition = class.definition(db); let class_definition = class.definition(db);
let typevar = TypeVarInstance::new( let typevar = TypeVarInstance::new(
db, db,