Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1774,6 +1774,25 @@ static_assert(is_subtype_of(type[B], Callable[[str], B]))
static_assert(not is_subtype_of(type[B], Callable[[int], B]))
```

### Dataclasses

Dataclasses synthesize a `__init__` method.

```py
from typing import Callable
from ty_extensions import TypeOf, static_assert, is_subtype_of
from dataclasses import dataclass

@dataclass
class A:
x: "A" | None

static_assert(is_subtype_of(type[A], Callable[[A], A]))
static_assert(is_subtype_of(type[A], Callable[[None], A]))
static_assert(is_subtype_of(type[A], Callable[[A | None], A]))
static_assert(not is_subtype_of(type[A], Callable[[int], A]))
```

### Bound methods

```py
Expand Down
44 changes: 25 additions & 19 deletions crates/ty_python_semantic/src/types/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,27 +661,33 @@ impl<'db> ClassType<'db> {
// same parameters as the `__init__` method after it is bound, and with the return type of
// the concrete type of `Self`.
let synthesized_dunder_init_callable =
if let Place::Type(Type::FunctionLiteral(dunder_init_function), _) =
dunder_init_function_symbol
{
let synthesized_signature = |signature: Signature<'db>| {
Signature::new(signature.parameters().clone(), Some(correct_return_type))
.bind_self()
if let Place::Type(ty, _) = dunder_init_function_symbol {
let signature = match ty {
Type::FunctionLiteral(dunder_init_function) => {
Some(dunder_init_function.signature(db))
}
Type::Callable(callable) => Some(callable.signatures(db)),
_ => None,
};

let synthesized_dunder_init_signature = CallableSignature::from_overloads(
dunder_init_function
.signature(db)
.overloads
.iter()
.cloned()
.map(synthesized_signature),
);
Some(Type::Callable(CallableType::new(
db,
synthesized_dunder_init_signature,
true,
)))
if let Some(signature) = signature {
let synthesized_signature = |signature: &Signature<'db>| {
Signature::new(signature.parameters().clone(), Some(correct_return_type))
.bind_self()
};

let synthesized_dunder_init_signature = CallableSignature::from_overloads(
signature.overloads.iter().map(synthesized_signature),
);

Some(Type::Callable(CallableType::new(
db,
synthesized_dunder_init_signature,
true,
)))
} else {
None
}
} else {
None
};
Expand Down
Loading