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

Type narrowing for unions Literal | uuid.UUID doesn't work #18569

Closed
zoola969 opened this issue Jan 30, 2025 · 2 comments
Closed

Type narrowing for unions Literal | uuid.UUID doesn't work #18569

zoola969 opened this issue Jan 30, 2025 · 2 comments
Labels
bug mypy got something wrong topic-type-narrowing Conditional type narrowing / binder

Comments

@zoola969
Copy link

Bug Report

When using the union of Literal type and uuid.UUID as a type, after comparing with a literal value, the value does not narrow to the type uuid.UUID.
However, this behavior is observed only when uuid.UUID is used as the type. If other types, such as built-ins and custom classes, are used instead, the comparison with a literal value results in the value narrowing to the appropriate type.

To Reproduce

https://mypy-play.net/?mypy=1.14.1&python=3.13&gist=04f8465218eabef5641c72b78e4a7e67

from typing import Literal
from uuid import UUID


type TLiteral = Literal["text"]
TEXT: TLiteral = "text"

# type T = int  # works good 
type T = UUID  # fails

def f(v: T | TLiteral) -> T | None:
    if v == TEXT:
        return None
    return v

Expected Behavior
Success: no issues found in 1 source file

Actual Behavior
error: Incompatible return value type (got "UUID | Literal['text']", expected "UUID | None"

Your Environment

  • Mypy version used: 1.14.1
  • Mypy command-line flags:
  • Mypy configuration options from mypy.ini (and other config files):
[tool.mypy]
plugins = ["pydantic.mypy"]
check_untyped_defs = true
enable_error_code = "explicit-override,unused-awaitable,ignore-without-code,truthy-bool,possibly-undefined,redundant-expr,redundant-self"
pretty = true
show_error_context = true
strict = true
warn_unreachable = true
  • Python version used: 3.13
@zoola969 zoola969 added the bug mypy got something wrong label Jan 30, 2025
@A5rocks A5rocks added the topic-type-narrowing Conditional type narrowing / binder label Jan 30, 2025
@A5rocks
Copy link
Collaborator

A5rocks commented Jan 30, 2025

Reproduce without uuid (and with less concepts):

from typing import Literal

class A:
    def __eq__(self, other: object) -> bool:  # necessary
        return isinstance(other, A)

def f(v: A | Literal["text"]) -> A | None:
    if v == "text":
        reveal_type(v)  # N: Revealed type is "Union[__main__.A, Literal['text']]"
        return None
    else:
        reveal_type(v)  # N: Revealed type is "Union[__main__.A, Literal['text']]"
        return v

I think the negative narrowing of == for literals is incorrect here.

@A5rocks
Copy link
Collaborator

A5rocks commented Jan 30, 2025

Duplicate of #16465

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

2 participants