@@ -4644,6 +4644,10 @@ impl<'db> GeneralCallableType<'db> {
4644
4644
iter_other : other_signature. parameters ( ) . iter ( ) ,
4645
4645
} ;
4646
4646
4647
+ // Collect all the standard parameters that have only been matched against a variadic
4648
+ // parameter which means that the keyword variant is still unmatched.
4649
+ let mut other_keywords = Vec :: new ( ) ;
4650
+
4647
4651
loop {
4648
4652
let Some ( next_parameter) = parameters. next ( ) else {
4649
4653
// All parameters have been checked or both the parameter lists were empty. In
@@ -4653,6 +4657,14 @@ impl<'db> GeneralCallableType<'db> {
4653
4657
4654
4658
match next_parameter {
4655
4659
EitherOrBoth :: Left ( self_parameter) => match self_parameter. kind ( ) {
4660
+ ParameterKind :: KeywordOnly { .. } | ParameterKind :: KeywordVariadic { .. }
4661
+ if !other_keywords. is_empty ( ) =>
4662
+ {
4663
+ // If there are any unmatched keyword parameters in `other`, they need to
4664
+ // be checked against the keyword-only / keyword-variadic parameters that
4665
+ // will be done after this loop.
4666
+ break ;
4667
+ }
4656
4668
ParameterKind :: PositionalOnly { default_type, .. }
4657
4669
| ParameterKind :: PositionalOrKeyword { default_type, .. }
4658
4670
| ParameterKind :: KeywordOnly { default_type, .. } => {
@@ -4727,14 +4739,25 @@ impl<'db> GeneralCallableType<'db> {
4727
4739
}
4728
4740
}
4729
4741
4730
- ( ParameterKind :: Variadic { .. } , ParameterKind :: PositionalOnly { .. } ) => {
4742
+ (
4743
+ ParameterKind :: Variadic { .. } ,
4744
+ ParameterKind :: PositionalOnly { .. }
4745
+ | ParameterKind :: PositionalOrKeyword { .. } ,
4746
+ ) => {
4731
4747
if !check_types (
4732
4748
other_parameter. annotated_type ( ) ,
4733
4749
self_parameter. annotated_type ( ) ,
4734
4750
) {
4735
4751
return false ;
4736
4752
}
4737
4753
4754
+ if matches ! (
4755
+ other_parameter. kind( ) ,
4756
+ ParameterKind :: PositionalOrKeyword { .. }
4757
+ ) {
4758
+ other_keywords. push ( other_parameter) ;
4759
+ }
4760
+
4738
4761
// We've reached a variadic parameter in `self` which means there can
4739
4762
// be no more positional parameters after this in a valid AST. But, the
4740
4763
// current parameter in `other` is a positional-only which means there
@@ -4749,14 +4772,17 @@ impl<'db> GeneralCallableType<'db> {
4749
4772
let Some ( other_parameter) = parameters. peek_other ( ) else {
4750
4773
break ;
4751
4774
} ;
4752
- if !matches ! (
4753
- other_parameter. kind( ) ,
4775
+ match other_parameter. kind ( ) {
4776
+ ParameterKind :: PositionalOrKeyword { .. } => {
4777
+ other_keywords. push ( other_parameter) ;
4778
+ }
4754
4779
ParameterKind :: PositionalOnly { .. }
4755
- | ParameterKind :: Variadic { .. }
4756
- ) {
4757
- // Any other parameter kind cannot be checked against a
4758
- // variadic parameter and is deferred to the next iteration.
4759
- break ;
4780
+ | ParameterKind :: Variadic { .. } => { }
4781
+ _ => {
4782
+ // Any other parameter kind cannot be checked against a
4783
+ // variadic parameter and is deferred to the next iteration.
4784
+ break ;
4785
+ }
4760
4786
}
4761
4787
if !check_types (
4762
4788
other_parameter. annotated_type ( ) ,
@@ -4828,11 +4854,15 @@ impl<'db> GeneralCallableType<'db> {
4828
4854
}
4829
4855
}
4830
4856
4831
- for other_parameter in other_parameters {
4857
+ for other_parameter in other_keywords . into_iter ( ) . chain ( other_parameters) {
4832
4858
match other_parameter. kind ( ) {
4833
4859
ParameterKind :: KeywordOnly {
4834
4860
name : other_name,
4835
4861
default_type : other_default,
4862
+ }
4863
+ | ParameterKind :: PositionalOrKeyword {
4864
+ name : other_name,
4865
+ default_type : other_default,
4836
4866
} => {
4837
4867
if let Some ( self_parameter) = self_keywords. remove ( other_name) {
4838
4868
match self_parameter. kind ( ) {
0 commit comments