allow multiple overloads/callables when inferring

This commit is contained in:
Douglas Creager 2025-12-03 11:20:30 -05:00
parent db5834dfd7
commit 77ce24a5bf
3 changed files with 28 additions and 27 deletions

View File

@ -624,8 +624,7 @@ class ClassWithNewAndInit:
def __init__(self, x: int) -> None: ... def __init__(self, x: int) -> None: ...
# TODO: revealed: ClassWithNewAndInit # revealed: ClassWithNewAndInit
# revealed: Unknown
reveal_type(accepts_callable(ClassWithNewAndInit)()) reveal_type(accepts_callable(ClassWithNewAndInit)())
class Meta(type): class Meta(type):
@ -660,10 +659,10 @@ class ClassWithOverloadedInit[T]:
def __init__(self, x: int | str) -> None: ... def __init__(self, x: int | str) -> None: ...
# TODO: revealed: ClassWithOverloadedInit[int] # TODO: revealed: ClassWithOverloadedInit[int]
# revealed: Unknown # revealed: Top[ClassWithOverloadedInit[Unknown]]
reveal_type(accepts_callable(ClassWithOverloadedInit)(0)) reveal_type(accepts_callable(ClassWithOverloadedInit)(0))
# TODO: revealed: ClassWithOverloadedInit[str] # TODO: revealed: ClassWithOverloadedInit[str]
# revealed: Unknown # revealed: Top[ClassWithOverloadedInit[Unknown]]
reveal_type(accepts_callable(ClassWithOverloadedInit)("")) reveal_type(accepts_callable(ClassWithOverloadedInit)(""))
class GenericClass[T]: class GenericClass[T]:

View File

@ -11966,6 +11966,10 @@ impl<'db> CallableTypes<'db> {
} }
} }
fn as_slice(&self) -> &SmallVec<[CallableType<'db>; 1]> {
&self.0
}
fn into_inner(self) -> SmallVec<[CallableType<'db>; 1]> { fn into_inner(self) -> SmallVec<[CallableType<'db>; 1]> {
self.0 self.0
} }

View File

@ -17,12 +17,11 @@ use crate::types::signatures::Parameters;
use crate::types::tuple::{TupleSpec, TupleType, walk_tuple_type}; use crate::types::tuple::{TupleSpec, TupleType, walk_tuple_type};
use crate::types::visitor::{TypeCollector, TypeVisitor, walk_type_with_recursion_guard}; use crate::types::visitor::{TypeCollector, TypeVisitor, walk_type_with_recursion_guard};
use crate::types::{ use crate::types::{
ApplyTypeMappingVisitor, BoundTypeVarIdentity, BoundTypeVarInstance, CallableTypes, ApplyTypeMappingVisitor, BoundTypeVarIdentity, BoundTypeVarInstance, ClassLiteral,
ClassLiteral, FindLegacyTypeVarsVisitor, HasRelationToVisitor, IsDisjointVisitor, FindLegacyTypeVarsVisitor, HasRelationToVisitor, IsDisjointVisitor, IsEquivalentVisitor,
IsEquivalentVisitor, KnownClass, KnownInstanceType, MaterializationKind, NormalizedVisitor, KnownClass, KnownInstanceType, MaterializationKind, NormalizedVisitor, Type, TypeContext,
Type, TypeContext, TypeMapping, TypeRelation, TypeVarBoundOrConstraints, TypeVarIdentity, TypeMapping, TypeRelation, TypeVarBoundOrConstraints, TypeVarIdentity, TypeVarInstance,
TypeVarInstance, TypeVarKind, TypeVarVariance, UnionType, declaration_type, TypeVarKind, TypeVarVariance, UnionType, declaration_type, walk_bound_type_var_type,
walk_bound_type_var_type,
}; };
use crate::{Db, FxOrderMap, FxOrderSet}; use crate::{Db, FxOrderMap, FxOrderSet};
@ -1650,27 +1649,26 @@ impl<'db> SpecializationBuilder<'db> {
} }
(Type::Callable(formal_callable), _) => { (Type::Callable(formal_callable), _) => {
let Some(actual_callable) = actual let Some(actual_callables) = actual.try_upcast_to_callable(self.db) else {
.try_upcast_to_callable(self.db)
.and_then(CallableTypes::exactly_one)
else {
return Ok(()); return Ok(());
}; };
let [formal_signature] = formal_callable.signatures(self.db).overloads.as_slice() let mut when = ConstraintSet::from(false);
else { for formal_signature in &formal_callable.signatures(self.db).overloads {
return Ok(()); for actual_callable in actual_callables.as_slice() {
}; for actual_signature in &actual_callable.signatures(self.db).overloads {
let [actual_signature] = actual_callable.signatures(self.db).overloads.as_slice() when.union(
else { self.db,
return Ok(()); formal_signature.when_constraint_set_assignable_to(
}; self.db,
actual_signature,
self.inferable,
),
);
}
}
}
let when = formal_signature.when_constraint_set_assignable_to(
self.db,
actual_signature,
self.inferable,
);
when.for_each_path(self.db, |path| { when.for_each_path(self.db, |path| {
for constraint in path.positive_constraints() { for constraint in path.positive_constraints() {
let typevar = constraint.typevar(self.db); let typevar = constraint.typevar(self.db);