gotta get those return types too

This commit is contained in:
Douglas Creager 2025-12-07 14:25:09 -05:00
parent c60560f39d
commit ecb9c1301b
1 changed files with 65 additions and 9 deletions

View File

@ -22,7 +22,9 @@ use super::{
semantic_index, semantic_index,
}; };
use crate::semantic_index::definition::{Definition, DefinitionKind}; use crate::semantic_index::definition::{Definition, DefinitionKind};
use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension}; use crate::types::constraints::{
ConstraintSet, IteratorConstraintsExtension, OptionConstraintsExtension,
};
use crate::types::function::{is_implicit_classmethod, is_implicit_staticmethod}; use crate::types::function::{is_implicit_classmethod, is_implicit_staticmethod};
use crate::types::generics::{ use crate::types::generics::{
GenericContext, InferableTypeVars, typing_self, walk_generic_context, GenericContext, InferableTypeVars, typing_self, walk_generic_context,
@ -398,13 +400,19 @@ impl<'db> CallableSignature<'db> {
) )
} }
/// Checks whether the given slice contains a single signature, and that signature is a
/// ParamSpec signature. If so, returns the [`BoundTypeVarInstance`] for the ParamSpec, along
/// with the return type of the signature.
fn signatures_is_single_paramspec( fn signatures_is_single_paramspec(
signatures: &[Signature<'db>], signatures: &[Signature<'db>],
) -> Option<BoundTypeVarInstance<'db>> { ) -> Option<(BoundTypeVarInstance<'db>, Option<Type<'db>>)> {
let [signature] = signatures else { let [signature] = signatures else {
return None; return None;
}; };
signature.parameters.as_paramspec() signature
.parameters
.as_paramspec()
.map(|bound_typevar| (bound_typevar, signature.return_ty))
} }
pub(crate) fn when_constraint_set_assignable_to( pub(crate) fn when_constraint_set_assignable_to(
@ -440,17 +448,33 @@ impl<'db> CallableSignature<'db> {
let other_is_single_paramspec = Self::signatures_is_single_paramspec(other_signatures); let other_is_single_paramspec = Self::signatures_is_single_paramspec(other_signatures);
match (self_is_single_paramspec, other_is_single_paramspec) { match (self_is_single_paramspec, other_is_single_paramspec) {
(Some(self_bound_typevar), Some(other_bound_typevar)) => { (
return ConstraintSet::constrain_typevar( Some((self_bound_typevar, self_return_type)),
Some((other_bound_typevar, other_return_type)),
) => {
let param_spec_matches = ConstraintSet::constrain_typevar(
db, db,
self_bound_typevar, self_bound_typevar,
Type::TypeVar(other_bound_typevar), Type::TypeVar(other_bound_typevar),
Type::TypeVar(other_bound_typevar), Type::TypeVar(other_bound_typevar),
relation, relation,
); );
let return_types_match = self_return_type.zip(other_return_type).when_some_and(
|(self_return_type, other_return_type)| {
self_return_type.has_relation_to_impl(
db,
other_return_type,
inferable,
relation,
relation_visitor,
disjointness_visitor,
)
},
);
return param_spec_matches.and(db, || return_types_match);
} }
(Some(self_bound_typevar), None) => { (Some((self_bound_typevar, self_return_type)), None) => {
let upper = let upper =
Type::Callable(CallableType::new( Type::Callable(CallableType::new(
db, db,
@ -459,16 +483,32 @@ impl<'db> CallableSignature<'db> {
)), )),
CallableTypeKind::ParamSpecValue, CallableTypeKind::ParamSpecValue,
)); ));
return ConstraintSet::constrain_typevar( let param_spec_matches = ConstraintSet::constrain_typevar(
db, db,
self_bound_typevar, self_bound_typevar,
Type::Never, Type::Never,
upper, upper,
relation, relation,
); );
let return_types_match = self_return_type.when_some_and(|self_return_type| {
other_signatures
.iter()
.filter_map(|signature| signature.return_ty)
.when_all(db, |other_return_type| {
self_return_type.has_relation_to_impl(
db,
other_return_type,
inferable,
relation,
relation_visitor,
disjointness_visitor,
)
})
});
return param_spec_matches.and(db, || return_types_match);
} }
(None, Some(other_bound_typevar)) => { (None, Some((other_bound_typevar, other_return_type))) => {
let lower = let lower =
Type::Callable(CallableType::new( Type::Callable(CallableType::new(
db, db,
@ -477,13 +517,29 @@ impl<'db> CallableSignature<'db> {
)), )),
CallableTypeKind::ParamSpecValue, CallableTypeKind::ParamSpecValue,
)); ));
return ConstraintSet::constrain_typevar( let param_spec_matches = ConstraintSet::constrain_typevar(
db, db,
other_bound_typevar, other_bound_typevar,
lower, lower,
Type::object(), Type::object(),
relation, relation,
); );
let return_types_match = other_return_type.when_some_and(|other_return_type| {
self_signatures
.iter()
.filter_map(|signature| signature.return_ty)
.when_all(db, |self_return_type| {
self_return_type.has_relation_to_impl(
db,
other_return_type,
inferable,
relation,
relation_visitor,
disjointness_visitor,
)
})
});
return param_spec_matches.and(db, || return_types_match);
} }
(None, None) => {} (None, None) => {}