(self, template: Instance)
| 734 | # Non-leaf types |
| 735 | |
| 736 | def visit_instance(self, template: Instance) -> list[Constraint]: |
| 737 | original_actual = actual = self.actual |
| 738 | res: list[Constraint] = [] |
| 739 | if isinstance(actual, (CallableType, Overloaded)) and template.type.is_protocol: |
| 740 | if "__call__" in template.type.protocol_members: |
| 741 | # Special case: a generic callback protocol |
| 742 | if not any(template == t for t in template.type.inferring): |
| 743 | template.type.inferring.append(template) |
| 744 | call = mypy.subtypes.find_member( |
| 745 | "__call__", template, actual, is_operator=True |
| 746 | ) |
| 747 | assert call is not None |
| 748 | if ( |
| 749 | self.direction == SUPERTYPE_OF |
| 750 | and mypy.subtypes.is_subtype(actual, erase_typevars(call)) |
| 751 | or self.direction == SUBTYPE_OF |
| 752 | and mypy.subtypes.is_subtype(erase_typevars(call), actual) |
| 753 | ): |
| 754 | res.extend(infer_constraints(call, actual, self.direction)) |
| 755 | template.type.inferring.pop() |
| 756 | if isinstance(actual, CallableType) and actual.fallback is not None: |
| 757 | if ( |
| 758 | actual.is_type_obj() |
| 759 | and template.type.is_protocol |
| 760 | and self.direction == SUPERTYPE_OF |
| 761 | ): |
| 762 | ret_type = get_proper_type(actual.ret_type) |
| 763 | if isinstance(ret_type, TupleType): |
| 764 | ret_type = mypy.typeops.tuple_fallback(ret_type) |
| 765 | if isinstance(ret_type, Instance): |
| 766 | res.extend( |
| 767 | self.infer_constraints_from_protocol_members( |
| 768 | ret_type, template, ret_type, template, class_obj=True |
| 769 | ) |
| 770 | ) |
| 771 | actual = actual.fallback |
| 772 | if isinstance(actual, TypeType) and template.type.is_protocol: |
| 773 | if self.direction == SUPERTYPE_OF: |
| 774 | a_item = actual.item |
| 775 | if isinstance(a_item, Instance): |
| 776 | res.extend( |
| 777 | self.infer_constraints_from_protocol_members( |
| 778 | a_item, template, a_item, template, class_obj=True |
| 779 | ) |
| 780 | ) |
| 781 | # Infer constraints for Type[T] via metaclass of T when it makes sense. |
| 782 | if isinstance(a_item, TypeVarType): |
| 783 | a_item = get_proper_type(a_item.upper_bound) |
| 784 | if isinstance(a_item, Instance) and a_item.type.metaclass_type: |
| 785 | res.extend( |
| 786 | self.infer_constraints_from_protocol_members( |
| 787 | a_item.type.metaclass_type, template, actual, template |
| 788 | ) |
| 789 | ) |
| 790 | |
| 791 | if isinstance(actual, Overloaded) and actual.fallback is not None: |
| 792 | actual = actual.fallback |
| 793 | if isinstance(actual, TypedDictType): |
nothing calls this directly
no test coverage detected