ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

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

2026/9/11 23:43:27 拓冰建站 浏览量
invalid-super-argument 规则深度解析:ruff(ty 类型检查器)如何静态校验 `super()` 调用实参 invalid-super-argument 规则深度解析ruffty 类型检查器如何静态校验super()调用实参【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruffsuper()是 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-checkerty一侧而非ruff_linter的传统 lint 规则集通过include_str!宏直接嵌入到 Rust 源码中的规则声明处见 crates/ty_python_semantic/src/types/diagnostic.rsdeclare_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()调用中的两类问题第一个实参不是合法的类字面量invalid class literal第二个实参不是第一个实参的实例或子类。对应地crates/ty_python_semantic/src/types/bound_super.rs 中定义了BoundSuperError枚举把出错的形态细分为可区分的错误变体pub(super) enum BoundSuperErrordb { /// The pivot class (first argument) is not a valid class object. InvalidPivotClassType { pivot_class: Typedb }, /// 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()) # its 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可以归纳出实际场景下用户会看到的信息形态第一个参数根本不是类InvalidPivotClassType当第一个实参被解析为实例等非类对象时消息为Argument is not a valid class并标注其实际类型例如Argument has type ...当实参是types.GenericAlias之类的别名实例时会给出专门消息如types.GenericAliasinstance ... is not a valid class。第二个参数为抽象/结构类型AbstractOwnerType例如以Callable这类抽象类型作第二实参时运行时isinstance/issubclass关系无法被可靠满足诊断会给出... is an abstract/structural type in super(...)若第二参数是带边界或约束的类型变量还会附带类型变量边界信息帮助定位是哪一个约束不满足。继承/实例关系检查失败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.rssuper-call-in-named-tuple-method检测在NamedTuple类方法中调用super()该场景运行时必然异常声明见 diagnostic.rs本次讨论的invalid-super-argument则专门负责实参静态类型契约校验。从数据流看BoundSuperType::build见 bound_super.rs在构造受绑定的 super 对象时会同时校验实参关系并返回Result一旦校验失败错误被转换为对应 lint 上报。因此这三条规则共同覆盖了super()从参数类型错误到隐式参数不可得再到调用上下文非法的完整出错面。如何验证与测试mdtest 驱动ty 系列的规则行为采用mdtestmarkdown 驱动的测试验证测试用例以 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),仅供参考