[spec] overload subtyping rules are too strict.
Nessuno ha ancora preso questa issue.
- Lingua principale
- Python
- Stelle
- 1.8k
- Fork
- 302
- Merge medio
- 23h
- PR unite (30g)
- 8
Descrizione
The typing spec states that, when A and B are potentially overloaded methods
If a callable
Bis overloaded with two or more signatures, it is assignable to callableAif at least one of the overloaded signatures inBis assignable toAIf a callable
Ais overloaded with two or more signatures, callableBis assignable toAifBis assignable to all of the signatures inA
However, this definition seems to be too strict. Consider the following example:
from typing import Protocol, Self, overload
class IntScalarOurs(Protocol):
def __add__(self, other: int | Self, /) -> Self: ...
class IntScalarTheirs(Protocol):
@overload
def __add__(self, other: int, /) -> Self: ...
@overload
def __add__(self, other: Self, /) -> Self: ...
These two protocols specify the exact same runtime behavior. Yet, following the rules of the spec, IntScalarOurs is assignable to IntScalarTheirs, but IntScalarTheirs is not assignable to IntScalarOurs.
Case 1: A=IntScalarOurs, B=IntScalarTheirs.
If a callable B is overloaded with two or more signatures, it is assignable to callable A if at least one of the overloaded signatures in B is assignable to A
- Is
(self, int) -> Selfassignable to(self, int | Self) -> Self? No, becauseintis not a supertype ofint | Self(contravariance) - Is
(self, Self) -> Selfassignable to(self, int | Self) -> Self? No, becauseSelfis not a supertype ofint | Self(contravariance)
Thus, IntScalarTheirs is not assignable to IntScalarOurs.
Case 2: A=IntScalarTheirs, B=IntScalarOurs.
If a callable A is overloaded with two or more signatures, callable B is assignable to A if B is assignable to all of the signatures in A
- Is
(self, int | Self) -> Selfassignable to(self, int) -> Self? Yes. - Is
(self, int | Self) -> Selfassignable to(self, Self) -> Self? Yes.
Thus, IntScalarOurs is assignable to IntScalarTheirs.
From a pure set-theoretic POV, it seems that subtyping functions should follow a very simply rule based on the domain.
$f <: g$ if and only if $\text{dom}(f) ⊇ \text{dom}(g)$ and $f(x) <: g(x)$ for all $x∈\text{dom}(g)$
What is currently specced appears to be a lemma for a sufficient condition, but not a necessary one.
Individual type-checkers can of course use such lemmas if the general case is too difficult to check/implement (and communicate that to their users), but shouldn't the spec be biased towards the theoretically principled point of view, when applicable?
Related Discussions
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia con le regole di sottotipizzazione degli overload nella sezione callables della specifica di typing e consulta la discussione correlata in typing/discussions/1782. Confronta le regole dichiarate con l'esempio IntScalarOurs e IntScalarTheirs, quindi determina se la specifica richieda una revisione basata su principi oppure una regola chiarita sulla condizione sufficiente.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- python
- Ambito
- compilers
- Tipo di issue
- Bug
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 35/100