python / python/typing

Spec/Conformance: subtyping callables with non-constant parameter mapping.

未关闭
#2,224 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

topic: typing spec
主要语言
Python
星标
1.8k
派生
302
平均合并
23 小时
30 天内合并 PR
8

描述

Consider the example below, which errors with all tested type checkers (mypy/pyright/ty/pyrefly):

from typing import Protocol

class Interval: ...

class Make(Protocol):
    def __call__(self, /, lower: float, upper: float) -> Interval: ...

def make_impl(
    string_or_lower: str | float | None = None,
    /,
    lower: float | None = None,
    upper: float | None = None,
) -> Interval: ...

def test() -> None:
    _f: Make = make_impl  # ❌️ type checkers error here.

I believe from a pure type theory POV, this assignment should be legal, because all legal arguments to Make are also legal arguments to make_impl. The spec phrases it in the same spirit:

A callable type B is assignable to a callable type A if the return type of B is assignable to the return type of A and the input signature of B accepts all possible combinations of arguments that the input signature of A accepts. All of the specific assignability rules described below derive from this general rule.

And I couldn't find anything else in https://typing.python.org/en/latest/spec/callables.html#assignability-rules-for-callables that would disallow this assignment.

It seems the type-checkers try to match the KEYWORD_OR_POSITIONAL parameters by name, which is incorrect. Make has 3 legal call signatures:

  1. Make(float, float)
  2. Make(float, upper=float)
  3. Make(lower=float, upper=float)

and all these 3 call signatures are supported by make_impl, but the parameter mapping is not constant:

  1. make_impl(float, float) -> {lower:string_or_lower, upper:lower}
  2. make_impl(float, upper=float) -> {lower:string_or_lower, upper:upper}
  3. make_impl(lower=float, upper=float) -> {lower:lower, upper:upper}

So either the spec should demand a constant parameter mapping, or this example should be added to the conformance tests.

贡献指南

这个仓库没有索引到贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从 issue 中链接的 callable 可赋值规则开始,并使用 mypy、pyright、ty 和 pyrefly 重现该示例。issue 未指定任何 repository 文件或 conformance-test 路径;完成取决于决定是在规范中明确常量参数映射,还是将此案例添加到 conformance tests 中。

由索引模型根据 Issue 内容生成。

评估

技术栈
python
领域
documentation, testing-qa
Issue 类型
文档
难度
5/5
预计耗时
一周以上
活跃度
冷清
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。