|
38 | 38 | Instance,
|
39 | 39 | LiteralType,
|
40 | 40 | NoneType,
|
| 41 | + NormalizedCallableType, |
41 | 42 | Overloaded,
|
42 | 43 | Parameters,
|
43 | 44 | ParamSpecType,
|
@@ -626,8 +627,10 @@ def visit_unpack_type(self, left: UnpackType) -> bool:
|
626 | 627 | return False
|
627 | 628 |
|
628 | 629 | def visit_parameters(self, left: Parameters) -> bool:
|
629 |
| - right = self.right |
630 |
| - if isinstance(right, Parameters) or isinstance(right, CallableType): |
| 630 | + if isinstance(self.right, Parameters) or isinstance(self.right, CallableType): |
| 631 | + right = self.right |
| 632 | + if isinstance(right, CallableType): |
| 633 | + right = right.with_unpacked_kwargs() |
631 | 634 | return are_parameters_compatible(
|
632 | 635 | left,
|
633 | 636 | right,
|
@@ -671,7 +674,7 @@ def visit_callable_type(self, left: CallableType) -> bool:
|
671 | 674 | elif isinstance(right, Parameters):
|
672 | 675 | # this doesn't check return types.... but is needed for is_equivalent
|
673 | 676 | return are_parameters_compatible(
|
674 |
| - left, |
| 677 | + left.with_unpacked_kwargs(), |
675 | 678 | right,
|
676 | 679 | is_compat=self._is_subtype,
|
677 | 680 | ignore_pos_arg_names=self.subtype_context.ignore_pos_arg_names,
|
@@ -1249,6 +1252,10 @@ def g(x: int) -> int: ...
|
1249 | 1252 | If the 'some_check' function is also symmetric, the two calls would be equivalent
|
1250 | 1253 | whether or not we check the args covariantly.
|
1251 | 1254 | """
|
| 1255 | + # Normalize both types before comparing them. |
| 1256 | + left = left.with_unpacked_kwargs() |
| 1257 | + right = right.with_unpacked_kwargs() |
| 1258 | + |
1252 | 1259 | if is_compat_return is None:
|
1253 | 1260 | is_compat_return = is_compat
|
1254 | 1261 |
|
@@ -1313,8 +1320,8 @@ def g(x: int) -> int: ...
|
1313 | 1320 |
|
1314 | 1321 |
|
1315 | 1322 | def are_parameters_compatible(
|
1316 |
| - left: Parameters | CallableType, |
1317 |
| - right: Parameters | CallableType, |
| 1323 | + left: Parameters | NormalizedCallableType, |
| 1324 | + right: Parameters | NormalizedCallableType, |
1318 | 1325 | *,
|
1319 | 1326 | is_compat: Callable[[Type, Type], bool],
|
1320 | 1327 | ignore_pos_arg_names: bool = False,
|
@@ -1535,11 +1542,11 @@ def new_is_compat(left: Type, right: Type) -> bool:
|
1535 | 1542 |
|
1536 | 1543 |
|
1537 | 1544 | def unify_generic_callable(
|
1538 |
| - type: CallableType, |
1539 |
| - target: CallableType, |
| 1545 | + type: NormalizedCallableType, |
| 1546 | + target: NormalizedCallableType, |
1540 | 1547 | ignore_return: bool,
|
1541 | 1548 | return_constraint_direction: int | None = None,
|
1542 |
| -) -> CallableType | None: |
| 1549 | +) -> NormalizedCallableType | None: |
1543 | 1550 | """Try to unify a generic callable type with another callable type.
|
1544 | 1551 |
|
1545 | 1552 | Return unified CallableType if successful; otherwise, return None.
|
@@ -1576,7 +1583,7 @@ def report(*args: Any) -> None:
|
1576 | 1583 | )
|
1577 | 1584 | if had_errors:
|
1578 | 1585 | return None
|
1579 |
| - return applied |
| 1586 | + return cast(NormalizedCallableType, applied) |
1580 | 1587 |
|
1581 | 1588 |
|
1582 | 1589 | def try_restrict_literal_union(t: UnionType, s: Type) -> list[Type] | None:
|
|
0 commit comments