Type check a super expression (non-lvalue).
(self, e: SuperExpr)
| 5695 | return callable_ctx.copy_modified(arg_names=e.arg_names), callable_ctx |
| 5696 | |
| 5697 | def visit_super_expr(self, e: SuperExpr) -> Type: |
| 5698 | """Type check a super expression (non-lvalue).""" |
| 5699 | |
| 5700 | # We have an expression like super(T, var).member |
| 5701 | |
| 5702 | # First compute the types of T and var |
| 5703 | types = self._super_arg_types(e) |
| 5704 | if isinstance(types, tuple): |
| 5705 | type_type, instance_type = types |
| 5706 | else: |
| 5707 | return types |
| 5708 | |
| 5709 | # Now get the MRO |
| 5710 | type_info = type_info_from_type(type_type) |
| 5711 | if type_info is None: |
| 5712 | self.chk.fail(message_registry.UNSUPPORTED_ARG_1_FOR_SUPER, e) |
| 5713 | return AnyType(TypeOfAny.from_error) |
| 5714 | |
| 5715 | instance_info = type_info_from_type(instance_type) |
| 5716 | if instance_info is None: |
| 5717 | self.chk.fail(message_registry.UNSUPPORTED_ARG_2_FOR_SUPER, e) |
| 5718 | return AnyType(TypeOfAny.from_error) |
| 5719 | |
| 5720 | mro = instance_info.mro |
| 5721 | |
| 5722 | # The base is the first MRO entry *after* type_info that has a member |
| 5723 | # with the right name |
| 5724 | index = None |
| 5725 | if type_info in mro: |
| 5726 | index = mro.index(type_info) |
| 5727 | else: |
| 5728 | method = self.chk.scope.current_function() |
| 5729 | # Mypy explicitly allows supertype upper bounds (and no upper bound at all) |
| 5730 | # for annotating self-types. However, if such an annotation is used for |
| 5731 | # checking super() we will still get an error. So to be consistent, we also |
| 5732 | # allow such imprecise annotations for use with super(), where we fall back |
| 5733 | # to the current class MRO instead. This works only from inside a method. |
| 5734 | if method is not None and is_self_type_like( |
| 5735 | instance_type, is_classmethod=method.is_class |
| 5736 | ): |
| 5737 | if e.info and type_info in e.info.mro: |
| 5738 | mro = e.info.mro |
| 5739 | index = mro.index(type_info) |
| 5740 | if index is None: |
| 5741 | if ( |
| 5742 | instance_info.is_protocol |
| 5743 | and instance_info != type_info |
| 5744 | and not type_info.is_protocol |
| 5745 | ): |
| 5746 | # A special case for mixins, in this case super() should point |
| 5747 | # directly to the host protocol, this is not safe, since the real MRO |
| 5748 | # is not known yet for mixin, but this feature is more like an escape hatch. |
| 5749 | index = -1 |
| 5750 | else: |
| 5751 | self.chk.fail(message_registry.SUPER_ARG_2_NOT_INSTANCE_OF_ARG_1, e) |
| 5752 | return AnyType(TypeOfAny.from_error) |
| 5753 | |
| 5754 | if len(mro) == index + 1: |
nothing calls this directly
no test coverage detected