Check is each solution satisfies the upper bound of the corresponding type variable. If it doesn't satisfy the bound, check if bound itself satisfies all constraints, and if yes, use it instead as a fallback solution.
(
solutions: list[Type | None],
original_vars: Sequence[TypeVarLikeType],
constraints: list[Constraint],
)
| 563 | |
| 564 | |
| 565 | def pre_validate_solutions( |
| 566 | solutions: list[Type | None], |
| 567 | original_vars: Sequence[TypeVarLikeType], |
| 568 | constraints: list[Constraint], |
| 569 | ) -> list[Type | None]: |
| 570 | """Check is each solution satisfies the upper bound of the corresponding type variable. |
| 571 | |
| 572 | If it doesn't satisfy the bound, check if bound itself satisfies all constraints, and |
| 573 | if yes, use it instead as a fallback solution. |
| 574 | """ |
| 575 | new_solutions: list[Type | None] = [] |
| 576 | for t, s in zip(original_vars, solutions): |
| 577 | if is_callable_protocol(t.upper_bound): |
| 578 | # This is really ad-hoc, but a proper fix would be much more complex, |
| 579 | # and otherwise this may cause crash in a relatively common scenario. |
| 580 | new_solutions.append(s) |
| 581 | continue |
| 582 | if s is not None and not is_subtype(s, t.upper_bound): |
| 583 | bound_satisfies_all = True |
| 584 | for c in constraints: |
| 585 | if c.op == SUBTYPE_OF and not is_subtype(t.upper_bound, c.target): |
| 586 | bound_satisfies_all = False |
| 587 | break |
| 588 | if c.op == SUPERTYPE_OF and not is_subtype(c.target, t.upper_bound): |
| 589 | bound_satisfies_all = False |
| 590 | break |
| 591 | if bound_satisfies_all: |
| 592 | new_solutions.append(t.upper_bound) |
| 593 | continue |
| 594 | new_solutions.append(s) |
| 595 | return new_solutions |
| 596 | |
| 597 | |
| 598 | def is_callable_protocol(t: Type) -> bool: |
no test coverage detected
searching dependent graphs…