Type narrowing not found for combination of overloaded optional argument and null guard

Aperta
#11,661 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

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

Direzione di ricerca

Inizia eseguendo il reproducer _scratch.py indicato con le versioni di mypy elencate e --show-error-codes, quindi confronta gli errori in func2, func3 e func4 con il comportamento previsto di narrowing. Il lavoro è completato quando i casi di overload e null-guard non producono più gli errori segnalati incompatible-assignment, None-call o unknown-function.

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

Descrizione

bug topic-overloads

Bug Report

Mypy fails to find type narrowings that use a combination of overloading and null checks.

To Reproduce

from __future__ import annotations
import typing as t


@t.overload
def func2(a: int,
          b: str,
          x: t.Callable[[int], int],
          y: t.Callable[[str], int]) -> tuple[int, int]: ...
@t.overload
def func2(a: int,
          b: str,
          x: t.Callable[[t.Union[int, str]], int]) -> tuple[int, int]: ...


def func2(a: int,
          b: str,
          x: t.Callable[[int], int],
          y: t.Optional[t.Callable[[str], int]] = None):
    y = y or x
    return x(a), y(b)


@t.overload
def func3(a: int,
          b: str,
          x: t.Callable[[int], int],
          y: t.Callable[[str], int]) -> tuple[int, int]: ...
@t.overload
def func3(a: int,
          b: str,
          x: t.Callable[[t.Union[int, str]], int]) -> tuple[int, int]: ...


def func3(a: int,
          b: str,
          x: t.Union[t.Callable[[int], int], t.Callable[[t.Union[int, str]], int]],
          y: t.Optional[t.Callable[[str], int]] = None):
    if y:
        y2 = y
    else:
        y2 = x
    return x(a), y2(b)


@t.overload
def func4(a: int,
          b: str,
          x: list[int],
          y: list[str]): ...
@t.overload
def func4(a: int,
          b: str,
          x: list[t.Union[int, str]]): ...


def func4(a: int,
          b: str,
          x: t.Union[list[int], list[t.Union[int, str]]],
          y: t.Optional[list[str]] = None):
    if y:
        y2 = y
    else:
        y2 = x
    x.append(a)
    y2.append(b)

Expected Behavior

My expectation is that in func2-func4, the Union type of x will always narrow down to support b as well as a when y is not supplied and x must be assigned to y/y2.

Actual Behavior

mypy==0.910:

$ mypy --show-error-codes _scratch.py 
_scratch.py:20: error: Incompatible types in assignment (expression has type "Union[Callable[[str], int], Callable[[int], int]]", variable has type "Optional[Callable[[str], int]]")  [assignment]
_scratch.py:21: error: "None" not callable  [misc]
_scratch.py:42: error: Incompatible types in assignment (expression has type "Union[Callable[[int], int], Callable[[Union[int, str]], int]]", variable has type "Callable[[str], int]")  [assignment]
_scratch.py:64: error: Incompatible types in assignment (expression has type "Union[List[int], List[Union[int, str]]]", variable has type "List[str]")  [assignment]

mypy==0.920.dev:

_scratch.py:20: error: Incompatible types in assignment (expression has type "Union[Callable[[str], int], Callable[[int], int]]", variable has type "Optional[Callable[[str], int]]")  [assignment]
_scratch.py:21: error: "None" not callable  [misc]
_scratch.py:42: error: Incompatible types in assignment (expression has type "Union[Callable[[int], int], Callable[[Union[int, str]], int]]", variable has type "Callable[[str], int]")  [assignment]
_scratch.py:64: error: Incompatible types in assignment (expression has type "Union[List[int], List[Union[int, str]]]", variable has type "List[str]")  [assignment]
_scratch.py:72: error: Cannot call function of unknown type  [operator]

Instead, no narrowing occurs and mypy declares the types incompatible, both when Callable is used and when a standard collection is used.

Your Environment

  • Mypy version used: 0.910 and 0.920+dev.cee5d3e9a29f43a10a8eeca760976657bf1689c9
  • Mypy command-line flags: --show-error-codes
  • Python version used: Python 3.8.0
  • Operating system and version: Microsoft Windows 10 [Version 10.0.19043.1348]
Lingua principale
Python
Stelle
20.6k
Fork
3.3k
Merge medio
1g 18h
PR unite (30g)
54

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.

Altre issue di python/mypy

Tutte le issue di python/mypy

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.