Thanks to visit codestin.com
Credit goes to github.com

Skip to content

structurally equivalent namedtuples can confuse mypy in unions in some cases #18520

Description

@asottile-sentry

Bug Report

some narrowing goes wrong and mypy ends up getting confused with a bunch of self-union types (A | A) and spurious errors

I'm not entirely sure the cause however

To Reproduce

from typing import NamedTuple


class AKey(NamedTuple):
    k: str

class A(NamedTuple):
    key: AKey
    s: str


class BKey(NamedTuple):
    k: str

class B(NamedTuple):
    key: BKey
    s: str


def f(x: A | B | str) -> A | B | str:
    if isinstance(x, str):
        return x
    else:
        return x._replace(s='wat')

Expected Behavior

no errors from the given snippet

Actual Behavior

$ mypy t3.py
t3.py:24: error: Invalid self argument "A | A" to attribute function "_replace" with type "Callable[[_NT, DefaultNamedArg(AKey, 'key'), DefaultNamedArg(str, 's')], _NT]"  [misc]
t3.py:24: error: Invalid self argument "B | B" to attribute function "_replace" with type "Callable[[_NT, DefaultNamedArg(BKey, 'key'), DefaultNamedArg(str, 's')], _NT]"  [misc]
t3.py:24: error: Incompatible return value type (got "A | B | A | B", expected "A | B | str")  [return-value]
Found 3 errors in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 1.14.0
  • Mypy command-line flags: n/a
  • Mypy configuration options from mypy.ini (and other config files): n/a
  • Python version used: 3.13.1

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions