mirror of https://github.com/astral-sh/ruff
use self annotation in synthesized __init__ callable
This commit is contained in:
parent
77ce24a5bf
commit
85e6143e07
|
|
@ -658,11 +658,14 @@ class ClassWithOverloadedInit[T]:
|
|||
def __init__(self: "ClassWithOverloadedInit[str]", x: str) -> None: ...
|
||||
def __init__(self, x: int | str) -> None: ...
|
||||
|
||||
# TODO: These unions are because we don't handle the ParamSpec in accepts_callable, so when
|
||||
# inferring a specialization through the Callable we lose the information about how the parameter
|
||||
# types distinguish the two overloads.
|
||||
# TODO: revealed: ClassWithOverloadedInit[int]
|
||||
# revealed: Top[ClassWithOverloadedInit[Unknown]]
|
||||
# revealed: ClassWithOverloadedInit[int] | ClassWithOverloadedInit[str]
|
||||
reveal_type(accepts_callable(ClassWithOverloadedInit)(0))
|
||||
# TODO: revealed: ClassWithOverloadedInit[str]
|
||||
# revealed: Top[ClassWithOverloadedInit[Unknown]]
|
||||
# revealed: ClassWithOverloadedInit[int] | ClassWithOverloadedInit[str]
|
||||
reveal_type(accepts_callable(ClassWithOverloadedInit)(""))
|
||||
|
||||
class GenericClass[T]:
|
||||
|
|
|
|||
|
|
@ -1199,39 +1199,45 @@ impl<'db> ClassType<'db> {
|
|||
// If the class defines an `__init__` method, then we synthesize a callable type with the
|
||||
// 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::Defined(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_callable = if let Place::Defined(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,
|
||||
};
|
||||
|
||||
if let Some(signature) = signature {
|
||||
let synthesized_signature = |signature: &Signature<'db>| {
|
||||
let self_annotation = signature
|
||||
.parameters()
|
||||
.get_positional(0)
|
||||
.and_then(Parameter::annotated_type);
|
||||
let return_type = self_annotation.unwrap_or(correct_return_type);
|
||||
let instance_ty = self_annotation.unwrap_or_else(|| Type::instance(db, self));
|
||||
Signature::new(signature.parameters().clone(), Some(return_type))
|
||||
.with_definition(signature.definition())
|
||||
.bind_self(db, Some(instance_ty))
|
||||
};
|
||||
|
||||
if let Some(signature) = signature {
|
||||
let synthesized_signature = |signature: &Signature<'db>| {
|
||||
let instance_ty = Type::instance(db, self);
|
||||
Signature::new(signature.parameters().clone(), Some(correct_return_type))
|
||||
.with_definition(signature.definition())
|
||||
.bind_self(db, Some(instance_ty))
|
||||
};
|
||||
let synthesized_dunder_init_signature = CallableSignature::from_overloads(
|
||||
signature.overloads.iter().map(synthesized_signature),
|
||||
);
|
||||
|
||||
let synthesized_dunder_init_signature = CallableSignature::from_overloads(
|
||||
signature.overloads.iter().map(synthesized_signature),
|
||||
);
|
||||
|
||||
Some(CallableType::new(
|
||||
db,
|
||||
synthesized_dunder_init_signature,
|
||||
true,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
Some(CallableType::new(
|
||||
db,
|
||||
synthesized_dunder_init_signature,
|
||||
true,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
match (dunder_new_function, synthesized_dunder_init_callable) {
|
||||
(Some(dunder_new_function), Some(synthesized_dunder_init_callable)) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue