Skip to content

mypy gives diagnostic on code Literal typing code accepted by pyright, pyrefly #19747

@jepler

Description

@jepler

Bug Report

Mypy issues a diagnostic for some code where pyrefly and pyright correctly intuit the Literal type of an expression.

This affected me in my project (jepler/wwvbpy#155) though I worked around it; the example here is distilled from my project.

To Reproduce

from typing import Literal

WWVBChannel = Literal["amplitude", "phase", "both"]

# OK in pyright, pyrefly
def f1(s: str) -> WWVBChannel | None:
    if s == "amplitude" or s == "phase" or s == "both":
        return s
    return None

# OK in pyrefly only; produces diagnostic in pyright
def f2(s: str) -> WWVBChannel | None:
    if s in {"amplitude", "phase", "both"}:
        return s
    return None

# OK in pyright, pyrefly
def f3(s: str) -> WWVBChannel | None:
    if s in ("amplitude", "phase", "both"):
        return s
    return None

Expected Behavior

mypy should be able to narrow the type of the s argument from str to WWVBChannel. There's at least one variant accepted by mypy that is accepted by these other two type checkers.

Actual Behavior

$ mypy --strict lit.py
/home/jepler/lit.py:8: error: Incompatible return value type (got "str", expected "Literal['amplitude', 'phase', 'both'] | None")  [return-value]
[and so on for all the 'return s' statements]

Your Environment

  • Mypy version used: mypy 1.17.1 (compiled: yes)
  • Mypy command-line flags: --strict
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: Python 3.13.5 (debian trixie amd64)
  • pyright version: pyright 1.1.404
  • pyrefly version: pyrefly 0.30.0

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions