python / python/mypy

Treating all numpy floating and complex types as interchangeable in overloads

Offen
#20,141 3 Kommentare 1 Reaktion 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

bug false-positive topic-overloads
Vorherrschende Sprache
Python
Sterne
20.6k
Forks
3.3k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

Bug Report

I am trying to specify that a function takes either an array of np.floating or np.complexfloating, and returns an array of the same type, using overloads. However, it seems like mypy is currently treating floating and complexfloating as completely interchangeable, instead of floating being a more specific type than complexfloating. As shown below, it also treats other numpy floating/complex types as interchangeable, e.g. np.float32 and np.complex128.

To Reproduce

from __future__ import annotations

from typing import overload

import numpy as np
from numpy.typing import NDArray


@overload
def test_type1(a: NDArray[np.floating]) -> NDArray[np.floating]:  ...
@overload
def test_type1(a: NDArray[np.complexfloating]) -> NDArray[np.complexfloating]: ...
def test_type1(a: NDArray[np.floating] | NDArray[np.complexfloating]) -> NDArray[np.floating] | NDArray[np.complexfloating]:
    return a


@overload
def test_type2(a: NDArray[np.complexfloating]) -> NDArray[np.complexfloating]: ...
@overload
def test_type2(a: NDArray[np.floating]) -> NDArray[np.floating]:  ...
def test_type2(a: NDArray[np.floating] | NDArray[np.complexfloating]) -> NDArray[np.floating] | NDArray[np.complexfloating]:
    return a


@overload
def test_type3(a: np.floating) -> np.floating:  ...
@overload
def test_type3(a: np.complexfloating) -> np.complexfloating: ...
def test_type3(a: np.floating | np.complexfloating) -> np.floating | np.complexfloating:
    return a


@overload
def test_type4(a: np.complexfloating) -> np.floating:  ...
@overload
def test_type4(a: np.floating) -> np.floating: ...
def test_type4(a: np.floating | np.complexfloating) -> np.floating | np.complexfloating:
    return a


@overload
def test_type5(a: np.float32) -> np.float32:  ...
@overload
def test_type5(a: np.complex128) -> np.complex128: ...
def test_type5(a: np.float32 | np.complex128) -> np.float32 | np.complex128:
    return a


@overload
def test_type6(a: float) -> float: ...
@overload
def test_type6(a: complex) -> float:  ...
def test_type6(a: float | complex) -> float | complex:
    # the only one that passes mypy
    return a

Actual Behavior

In version 1.15.0 the code above passes mypy. In version 1.16.0 and later, it gives:

mypy_test.py:12: error: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader [overload-cannot-match] mypy_test.py:20: error: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader [overload-cannot-match] mypy_test.py:28: error: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader [overload-cannot-match] mypy_test.py:36: error: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader [overload-cannot-match] mypy_test.py:44: error: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader [overload-cannot-match]

Expected Behavior

The errors for line 20 and 36 (test_type2 and test_type4) are correct errors as I understand the intended function of this warning. test_type6 correctly passes, consistent with the documented behavior of this check. However, the other 3 functions should pass with no warning, but are generating one.

Your Environment

I have tested and get the errors with mypy versions 1.16.0 and 1.18.2. The numpy version is 2.2.6 and python 3.13.7.

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Reproduziere die gemeldeten Diagnosen aus mypy_test.py anhand der bereitgestellten overload-Beispiele und vergleiche das Verhalten über die genannten mypy-Versionen hinweg. Verfolge die Prüfung overload-cannot-match und überprüfe anschließend, dass test_type1, test_type3 und test_type5 erfolgreich sind, während test_type2 und test_type4 weiterhin Fehler melden.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
numpy, python
Bereich
devtools, tooling
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
42/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.