Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect union narrowing in chained conditionals #12208

Closed
JaviFuentes94 opened this issue Feb 18, 2022 · 6 comments
Closed

Incorrect union narrowing in chained conditionals #12208

JaviFuentes94 opened this issue Feb 18, 2022 · 6 comments
Labels
bug mypy got something wrong topic-type-narrowing Conditional type narrowing / binder

Comments

@JaviFuentes94
Copy link

Bug Report
Hey there!

I have recently encountered this case:

class Animal:
    name: Literal["animal"]
    n_legs: int

class Plant:
    name: Literal["plant"]

def get_n_legs(item: Union[Animal, Plant]):
    if item.name == "animal" and item.n_legs > 6:    # This fails mypy with union-attr for n_legs in Plant
        return "Many" 

Expected Behavior

Mypy should be able to narrow down chained conditionals as presented. It seems that pylance has no problems with it, for example.

@JaviFuentes94 JaviFuentes94 added the bug mypy got something wrong label Feb 18, 2022
@erictraut
Copy link

Which version of mypy are you using? I'm not able to repro this error with the latest published version.

@JelleZijlstra
Copy link
Member

@JelleZijlstra JelleZijlstra added the topic-type-narrowing Conditional type narrowing / binder label Mar 19, 2022
@JaviFuentes94
Copy link
Author

JaviFuentes94 commented Mar 22, 2022

Hello again, sorry I made a mistake while testing my minimal example. The problem comes with a Literal that is an enum field:

from typing_extensions import Literal
from typing import Union, Dict
import enum

class Types(str, enum.Enum):
    animal = "animal"
    plant = "plant"


class Animal:
    name: Literal[Types.animal]
    n_legs: int

class Plant:
    name: Literal[Types.plant]

def get_n_legs(item: Union[Animal, Plant]):
    if item.name == Types.animal and item.n_legs > 6:   
        return "Many" 

Here you can reproduce it: https://mypy-play.net/?mypy=latest&python=3.10&gist=dfcdd1d12e53c80d0e58ba5ed8750ccf

@JelleZijlstra JelleZijlstra reopened this Mar 22, 2022
@mikaelarguedas
Copy link

mikaelarguedas commented Mar 4, 2023

Hey there,

I believe I ran into another occurrence of this. It looks like the type has not been narrowed by the first if statement.
Happens with latest mypy on Python3.8.
Trying it on https://mypy-play.net looks to happen on more recent versions of Python as well.

Reproducible example: https://mypy-play.net/?mypy=latest&python=3.11&flags=verbose&gist=07d004a22a748059c834ff42d690c2ed

from typing import Optional, Union


class RangeVals:
    """Hold a parameter value range."""

    def __init__(
        self,
        min_val: Union[int, float],
        max_val: Union[int, float],
    ) -> None:
        self.min_val = min_val
        self.max_val = max_val


def functionn(default_val: Union[str, float, int], rangeval: RangeVals):
    if type(default_val) != type(rangeval.min_val):
        raise TypeError("foo")
    if default_val < rangeval.min_val:
        raise ValueError("bar")


functionn("abc", RangeVals(min_val=3, max_val=10))

@erictraut
Copy link

The original bug in this issue appears to have been fixed in mypy 1.4.

@mikaelarguedas, your issue is unrelated to OP's bug. The behavior in your sample is expected behavior in mypy.

@hauntsaninja
Copy link
Collaborator

I fixed this in #11521

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-type-narrowing Conditional type narrowing / binder
Projects
None yet
Development

No branches or pull requests

5 participants