news 2026/9/10 20:22:39

invalid-super-argument 规则深度解析:ruff(ty 类型检查器)如何静态校验 `super()` 调用实参

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
invalid-super-argument 规则深度解析:ruff(ty 类型检查器)如何静态校验 `super()` 调用实参

invalid-super-argument 规则深度解析:ruff(ty 类型检查器)如何静态校验super()调用实参

【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff

super()是 Python 面向对象编程中委托方法调用的基石,但它的实参契约(第一个参数必须是类、第二个参数必须是该类的实例或子类)常常被误用,直到运行时才抛出TypeError。本文围绕 ruff 仓库中 ty(类型检查器)的invalid-super-argument规则文档展开,结合其声明与实现源码,讲清楚该规则检测什么、为什么值得检查、错误消息如何生成,以及它与其他super()相关规则的分工,帮助读者理解类型检查器如何在编译期把这类错误提前暴露出来。

规则文档与定位

本规则的用户文档位于 crates/ty_python_semantic/resources/lint_docs/invalid-super-argument.md,以"What it does / Why is this bad / Examples / References"的标准格式阐述规则语义。它属于本仓库 type-checker(ty)一侧(而非ruff_linter的传统 lint 规则集),通过include_str!宏直接嵌入到 Rust 源码中的规则声明处,见 crates/ty_python_semantic/src/types/diagnostic.rs:

declare_lint! { #[doc = include_str!("../../resources/lint_docs/invalid-super-argument.md")] pub(crate) static INVALID_SUPER_ARGUMENT = { summary: "detects invalid arguments for `super()`", status: LintStatus::stable("0.0.1-alpha.1"), default_level: Level::Error, } }

从源码声明可以确认三条事实:

  • 规则名称invalid-super-argument,人类可读摘要为"detects invalid arguments forsuper()";
  • 默认级别为Error:与一般先以 warning 放行的风格不同,这类问题默认即按错误上报;
  • 稳定于0.0.1-alpha.1:属于 ty 类型检查器早期便确立的稳定诊断。

规则检测什么:两类无效实参

根据规则文档,该规则检测super()调用中的两类问题:

  1. 第一个实参不是合法的类字面量(invalid class literal);
  2. 第二个实参不是第一个实参的实例或子类

对应地,crates/ty_python_semantic/src/types/bound_super.rs 中定义了BoundSuperError枚举,把"出错的形态"细分为可区分的错误变体:

pub(super) enum BoundSuperError<'db> { /// The pivot class (first argument) is not a valid class object. InvalidPivotClassType { pivot_class: Type<'db> }, /// The owner (second argument) has an abstract / structural type, /// so the runtime isinstance/issubclass relationship is ill-defined. AbstractOwnerType { ... }, /// The isinstance/issubclass condition fails for concrete types. FailingConditionCheck { ... }, ... }

也就是说,实现层把"第一个参数不是类"(InvalidPivotClassType)与"第二个参数与第一个参数不满足继承/实例关系"(FailingConditionCheck)拆成独立分支,以便生成精确的错误消息;此外对第二参数为抽象/结构类型或类型变量约束无法满足的情形(AbstractOwnerType)也单独给出提示。这些分支统一在BoundSuperError::report_diagnostic中通过context.report_lint(&INVALID_SUPER_ARGUMENT, node)上报告警,触发位置见 bound_super.rs。

运行时契约:为什么会TypeError

文档"Why is this bad?"解释了被检查对象背后的语义。super(type, obj)的合法条件为:

  • 第一个实参必须是(class);
  • 第二个实参必须满足下列二者之一:
    • isinstance(obj, type)True,或
    • issubclass(obj, type)True

违反这一关系时,Python 解释器会在运行时抛出TypeError。由于这类错误发生在方法调用的时刻、难以从语法层面察觉,类型检查器在静态分析阶段报出invalid-super-argument,相当于把运行时崩溃提前到编辑期。

文档示例逐行拆解

规则文档给出了完整可运行的示例。沿用原文档并补充注释说明:

class A: ... class B(A): ... super(A, B()) # it's okay! `A` satisfies `isinstance(B(), A)` # `A()` is not a class super(A(), B()) # error # `A()` does not satisfy `isinstance(A(), B)` super(B, A()) # error # `A` does not satisfy `issubclass(A, B)` super(B, A) # error

逐个分析:

调用判定原因
super(A, B())✅ 合法B继承自AB()A的实例,满足isinstance(B(), A)
super(A(), B())error第一个实参A()是实例而非类,不满足"第一个参数必须是类"
super(B, A())errorA()不是B的实例(A是父类,实例方向相反),isinstance(A(), B)不成立
super(B, A)errorA不是B的子类,issubclass(A, B)不成立

注意第三个与第四个例子体现了两个独立的检查维度:super第二实参既可以传实例(须满足isinstance)也可以传类(须满足issubclass,两种形态都必须与第一个实参构成"祖先/后代"方向一致的继承链。这与 mdtest 用例 crates/ty_python_semantic/resources/mdtest/class/super.md 中的行为一致——例如super(B, C())会因从B起查找b属性失败而报[unresolved-attribute],而super(A, C()).aa可以正常解析,直观反映了 super 沿 MRO 从 pivot class(第一个实参)之后开始查找的语义。

源码级佐证:报错信息的三类典型形态

文档只描述"报 error",而实现给出了比文档更细的错误消息分类。结合 bound_super.rs 的report_diagnostic,可以归纳出实际场景下用户会看到的信息形态:

  1. 第一个参数根本不是类InvalidPivotClassType):当第一个实参被解析为实例等非类对象时,消息为Argument is not a valid class,并标注其实际类型,例如Argument has type ...;当实参是types.GenericAlias之类的别名实例时,会给出专门消息(如types.GenericAliasinstance ... is not a valid class)。

  2. 第二个参数为抽象/结构类型AbstractOwnerType):例如以Callable这类抽象类型作第二实参时,运行时isinstance/issubclass关系无法被可靠满足,诊断会给出... is an abstract/structural type in super(...);若第二参数是带边界或约束的类型变量,还会附带类型变量边界信息,帮助定位是"哪一个约束不满足"。

  3. 继承/实例关系检查失败FailingConditionCheck):消息形如... is not an instance or subclass of ... in super(A, B) call,与文档中super(B, A)/super(B, A())的报错场景一一对应;当涉及类型变量时,还会追加一条 info,指出bounds_or_constraints中具体哪一项与 pivot class 不兼容。

这种"枚举区分错误形态 → 逐分支定制消息 → 类型变量附加边界提示"的结构,是 ty 诊断体系里"对Type与类型变量给出可读信息"的通用做法,同一文件 diagnostic.rs 中大量report_*函数也遵循此模式。

与其他 super() 相关规则的边界

invalid-super-argument只关心显式双实参形式的super(pivot, owner)是否满足契约。而super()还有隐式零参/单参形态,以及在不同类上下文中的特殊性。本仓库把这些问题拆分为不同规则,避免一个规则职责过载:

  • unavailable-implicit-super-arguments:检测super()调用中隐式实参不可用的情形(例如解释器无法从__class__单元或所在函数推导出 pivot class 与 owner),对应BoundSuperError::UnavailableImplicitArguments变体,声明见 diagnostic.rs;
  • super-call-in-named-tuple-method:检测在NamedTuple类方法中调用super()(该场景运行时必然异常),声明见 diagnostic.rs;
  • 本次讨论的invalid-super-argument则专门负责实参静态类型契约校验。

从数据流看,BoundSuperType::build(见 bound_super.rs)在构造受绑定的 super 对象时会同时校验实参关系并返回Result;一旦校验失败,错误被转换为对应 lint 上报。因此这三条规则共同覆盖了super()从"参数类型错误"到"隐式参数不可得"再到"调用上下文非法"的完整出错面。

如何验证与测试:mdtest 驱动

ty 系列的规则行为采用mdtest(markdown 驱动的测试)验证:测试用例以 Markdown 文档编写,代码块中内嵌# error: [invalid-super-argument]之类的注解标记,由 crates/ty_python_semantic/mdtest.py 生成并跑出快照。仓库内可见的证据包括:

  • 测试主体用例文档 crates/ty_python_semantic/resources/mdtest/class/super.md,其中包含# error: [invalid-super-argument]标注,覆盖"第二参数为函数/普通对象"等边界输入,例如对函数对象super(object, x)即标注该错误;
  • 生成的快照存放于 crates/ty_python_semantic/resources/mdtest/snapshots,含super.md ... Invalid Usages ...系列.snap文件;
  • 测试入口位于 crates/ty_python_semantic/tests/mdtest.rs。

读者若想复现或扩展这类用例,只需在super.md中新增带# error: [invalid-super-argument]注解的代码块并重新生成快照即可。规则的完整清单与说明也汇总在 crates/ty/docs/rules.md。

小结

invalid-super-argument是 ty 类型检查器对super(type, obj)运行时契约的静态建模:它校验第一个实参是否为类、第二个实参是否满足isinstance/issubclass关系,把本会在运行期触发的TypeError提前到静态分析阶段以Error级别暴露。通过本文可以掌握:该规则的声明位置与默认配置(diagnostic.rs)、判定与报错的三类实现分支(bound_super.rs),以及它与隐式实参、NamedTuple上下文等相邻规则的边界,从而在理解既有代码报错时能快速定位问题根因。

【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 20:21:56

数字序列1414141在开发与文化中的多重应用解析

1. 项目背景解析 "1414141"这个看似简单的数字序列&#xff0c;实际上蕴含着丰富的可能性。作为从业十余年的数字文化研究者&#xff0c;我发现这类数字组合往往在以下领域具有特殊意义&#xff1a; 游戏领域&#xff1a;常见于角色ID、道具编号或特殊关卡代码 编程…

作者头像 李华
网站建设 2026/9/10 20:18:07

AI画图新利器:2.9万星diagram skill,让AI自动生成架构图与流程图

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 20:17:32

CANN/ge获取编译图摘要API

GetCompiledGraphSummary 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、T…

作者头像 李华
网站建设 2026/9/10 20:16:51

技术博客写作:从项目标题到关键词的SEO实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 20:13:26

CANN/ge图引擎SetOutputAttr函数

SetOutputAttr 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、TensorFlow …

作者头像 李华
网站建设 2026/9/10 20:11:29

SpringBoot测试进阶指南:从MockMvc到Testcontainers的完整实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华