python / python/mypy

mypy incorrectly flags a type-var error when a descriptor overrides a protocol property in a different file.

Aperta
#20,317 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

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

Descrizione

Bug Report

To Reproduce

  • Create an app.py file with this inside:
from __future__ import annotations

from typing import Protocol

# PROTOCOL
class ServiceProto(Protocol):
    @property
    def value(self) -> int: ...

# DESCRIPTOR
class Descriptor:
    def __get__(self, instance: ServiceImpl, owner: type[ServiceImpl]) -> int:
        return 5

# IMPLEMENTATION
class ServiceImpl:
    value = Descriptor()

class App[ServiceT: ServiceProto]:
    def __init__(self, service: ServiceT) -> None:
        self.service = service
  • create a second file (important) with this inside (mine is named run.py):
from __future__ import annotations

from .app import App, ServiceImpl

def bootstrap() -> App[ServiceImpl]:
    return App(ServiceImpl())

Expected Behavior
No errors

Actual Behavior

mypy src/
run.py:5: error: Type argument "ServiceImpl" of "App" must be a subtype of "ServiceProto"  [type-var]
run.py:6: error: Value of type variable "ServiceT" of "App" cannot be "ServiceImpl"  [type-var]
Found 2 errors in 1 file (checked 3 source files)

Your Environment

  • Mypy version used: mypy 1.18.2 (compiled: yes)
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: Python 3.13.7 (via uv)

Weird Behavior

Merge both files, remove redundant imports. No more errors.

PS: Feel free to edit the title. This was a hard one to describe in one sentence without knowing the root cause.
PPS: This is a toy example with integers to illustrate the bug. My real use case is more complex: the descriptor is a lazy instantiator that works like cached_property (the descriptor is given a class object on instantiation, it instantiates and caches an instance of that class on the owning service instance, then serves the cached instance on further accesses).

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

Riproduci il report usando i file separati app.py e run.py, quindi esegui mypy src/ con Python 3.13.7 e mypy 1.18.2. Traccia come il ServiceImpl supportato da descriptor venga verificato rispetto a ServiceProto oltre il confine tra i file e come App[ServiceImpl] produca i type-var errors. Il lavoro è completato quando l'esempio composto da due file non segnala errori e il comportamento rimane coperto da un test di regressione appropriato.

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

Valutazione

Stack tecnologico
python
Ambito
compilers, 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.