DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

mypy 拒绝 Annotated[Self],保留接收者类型而非删掉元数据

mypy 识别接收者类型时漏过 Annotated 包装,会误拒合法 Self。采用递归识别修复,分别验证实例方法与类方法,并保留类型别名包装的边界。

方法写成 self: Self 可以通过,换成 self: Annotated[Self, "tag"] 就报 Method cannot have explicit self annotation and Self type [misc],先检查 mypy 是否识别了包装里面的接收者类型。删除元数据虽然可能避开报错,也会丢掉原先为其他工具保留的信息。

这个问题在 mypy 2.3.1、Python 3.13.4、openSUSE Tumbleweed 的默认配置下有明确复现。Annotated 允许不解释元数据的工具按内部类型处理,但旧 is_expected_self_type 没有穿过这一层,误把本来合法的 Self 当成与显式接收者注解冲突的情况。

mypy 2.4.0 的正式修补递归检查 Annotated 的第一个类型参数,实例方法和类方法的识别路径都有对应处理。它不解析 "tag" 的业务含义,也不负责让所有类型包装都变成 Self。

在运行检查的工具环境中选择包含修补的版本:

python -m pip install "mypy==2.4.0"
python -m mypy --version
python -m mypy repro.py

把下面的示例保存为 repro.py。从 typing 导入 Self 需要 Python 3.11 或以上;实际环境还应符合项目所选 mypy 的支持范围。

from typing import Annotated, Self

class Foo:
    def works(self: Self, x: int) -> None:
        pass

    def fails(self: Annotated[Self, "tag"], x: int) -> None:
        pass

    @classmethod
    def class_method(cls: Annotated[type[Self], "tag"], x: int) -> None:
        pass

验收保留元数据和显式接收者,确认原来的 misc 误报消失,再检查项目其他类型诊断。只测没有包装的第一种方法,不能证明补丁已经覆盖 Annotated;把整个文件排除,也无法证明检查器仍在工作。

如果项目主动启用了 redundant-self,它可能对冗余的显式 Self 给出另一种提醒。应区分错误码和配置意图,不把这份提醒当成上述 misc 回归仍在。既有检查规则应按项目要求保留。

另一个边界是用身份类型别名再包装接收者,例如 Python 3.12 起的 type Ident[T] = T,随后写 self: Ident[Self]。已有后案仍出现相近拒绝,而这份补丁只明确处理直接的 Annotated 路径;不能从前面三种形式通过推断身份别名也已正常。保留这种输入的最小例另查,不将别名问题归为元数据内容写错。

最后核对编辑器、终端与 CI 实际调用的 mypy 版本,按项目原来的配置再运行完整检查。最小例恢复只确认这一识别路径,不能替代项目其他类型规则和业务测试;仍有错误时保留准确的注解形态与错误码,避免把所有显式接收者问题都归为同一处遗漏。