import types
from typing import Callable, Any


class Foo:
    def __init__(self, f: Callable[[Any, str], str] = lambda this, x: x) -> None:
        # エラーにならない!
        self.iden: Callable[[str], int] = types.MethodType(f, self)


i: int

foo = Foo()
i = foo.iden("a")  # pylint: disable=not-callable
print(i)

既存のクラス階層に対して、テンプレートメソッドのようなことをやりたくなり、クラス階層の整合性を考えた結果、クラスを継承しながらオーバーライドする形式ではなく、上記のように、テンプレートメソッドをコンストラクタの引数にとる形式にするのが良いであろう、という結論に達しました。(このクラスはすでにいろいろなクラスで継承されていて、それらすべての derived クラスに対してテンプレートメソッドをオーバーライドするクラスを定義するのは辛い)

上記は、今回の問題を再現するために単純化したコードです。このコードは、コードとして実行すれば、問題なく実行され (コードとしては正しい) 、また mypy の検査も pass するのですが、その type annotation は間違っています。というのも、 Foo のコンストラクタの第一引数である f は、 (Any, str) => str というシグネチャを持っているにも関わらず、コンストラクタの初期化において (Foo, str) => int というシグネチャを持つフィールドに代入されているからです。そして、これはたとえばグローバルの i 変数の型を str にするとエラーになることから、この間違った型宣言によって mypy の推論は実行されていることが確認できます。

質問

mypy において、 MethodType まわりの型推論において、その不整合を検出することは可能ですか?

環境

  • mypy 0.701