python / python/mypy

Overloads with Generics "does not accept all possible arguments"

Aperta
#19,053 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

bug topic-overloads
Lingua principale
Python
Stelle
20.6k
Fork
3.3k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

I have a function whose return type is determined by the type of an input parameter (with a default value). I have attempted to type-hint it with generics. I get "error: Overloaded function implementation does not accept all possible arguments of signature".

To Reproduce

In the toy example below, the function has two return types (original-type or list) depending on two possible types of the force_list input (Force or NoForce). For completeness I have overloaded all 4 permutations of the input and output types.

Playground: https://mypy-play.net/?mypy=latest&python=3.12&gist=283290e33e2618dfcdf447513d0f4543

  from typing import TypeVar, assert_type, overload
  
  class Force: ...
  ForceInstance = Force()
  
  class NoForce: ...
  NoForceInstance = NoForce()
  
  T = TypeVar("T")
  
  @overload
  def list_or_orig(x: list[T], force_list: Force = ...) -> list[T]: ...
  
  @overload
  def list_or_orig(x: list[T], force_list: NoForce = ...) -> list[T]: ...
  
  @overload
  def list_or_orig(x: T, force_list: Force = ...) -> list[T]: ...
  
  @overload
  def list_or_orig(x: T, force_list: NoForce = ...) -> T: ...
  
  def list_or_orig(x: list[T] | T, force_list: Force | NoForce = ForceInstance) -> list[T] | T:
      """Return a list or scalar depending on force_list flag."""
      if isinstance(x, list):
          return x
      elif isinstance(force_list, Force):
          return [x]
      else:
          return x
  
  
  a_list = list_or_orig(1)  # Since default is Force, this will return list[int]
  assert_type(a_list, list[int])
  
  b_list = list_or_orig(1, ForceInstance)
  assert_type(b_list, list[int])
  
  a_int = list_or_orig(1, NoForceInstance)  # This will return int
  assert_type(a_int, int)

Expected Behavior

No errors when running through mypy.

Actual Behavior

main.py:29: error: Overloaded function implementation does not accept all possible arguments of signature 1  [misc]
main.py:29: error: Overloaded function implementation does not accept all possible arguments of signature 2  [misc]
Found 2 errors in 1 file (checked 1 source file)

Notes

If I replace the generic type T with a specific type, say, int then it's fine.

I appreciate there is an ambiguity between list[T] and T but have included the less-general list[T] first in the overloads.

The same code passes in the pyright playground.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia eseguendo con mypy l’esempio Python minimo dell’issue e confronta il risultato con il comportamento di Pyright collegato. Traccia il controllo di compatibilità dell’implementazione di overload che segnala le firme 1 e 2. Il lavoro è completato quando l’esempio non produce errori di compatibilità e conserva i risultati assert_type mostrati.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
devtools
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.