python / python/mypy

Treating all numpy floating and complex types as interchangeable in overloads

Ouverte
#20,141 3 commentaires 1 réaction 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

bug false-positive topic-overloads
Langage dominant
Python
Étoiles
20.6k
Forks
3.3k
Métriques de merge des PR
Métriques de PR en attente

Description

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.

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Reproduisez les diagnostics signalés par mypy_test.py à l’aide des exemples de overload fournis et comparez le comportement entre les versions de mypy mentionnées. Suivez la vérification overload-cannot-match, puis vérifiez que test_type1, test_type3 et test_type5 passent tandis que test_type2 et test_type4 continuent de signaler des erreurs.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
numpy, python
Domaine
devtools, tooling
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
42/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.