Skip to content

adjust contextlib.nullcontext.__init__ signature to fix divergences in type checkers#15482

Merged
srittau merged 1 commit intopython:mainfrom
pinterior:update-nullcontext-overload
Mar 4, 2026
Merged

adjust contextlib.nullcontext.__init__ signature to fix divergences in type checkers#15482
srittau merged 1 commit intopython:mainfrom
pinterior:update-nullcontext-overload

Conversation

@pinterior
Copy link
Contributor

currently contextlib.nullcontext.__init__ has two overloads with ambiguous parameter types, which result in the following:

  1. mypy infers nullcontext[int] | nullcontext[None] if enter_result is int | None
  2. pyright infers nullcontext[None] when enter_result is Any or Unknown

@overload
def __init__(self: nullcontext[None], enter_result: None = None) -> None: ...
@overload
def __init__(self: nullcontext[_T], enter_result: _T) -> None: ... # pyright: ignore[reportInvalidTypeVarUse] #11780

this PR removes the enter_result parameter from the first overload of nullcontext.__init__, making both mypy and pyright infer the same type.

Check

from contextlib import nullcontext as nc
from typing import Any

def f(a: Any, s: list, o: int | None):
    reveal_type(nc())     # None
    reveal_type(nc(None)) # None

    reveal_type(nc(""))   # str
    reveal_type(nc(123))  # int

    reveal_type(nc(a))    # Any
    reveal_type(nc(s[0])) # Unknown (pyright), Any (mypy)

    # Optional
    reveal_type(nc(o))              # int | None
    _a: nc[int | None] = nc(o)      # mypy: error -> ok, pyright: ok -> ok
    _b: nc[int] | nc[None] = nc(o)  # mypy: ok -> error, pyright: error -> error

Without patch

$ mypy nc.py 
nc.py:5: note: Revealed type is "contextlib.nullcontext[None]"
nc.py:6: note: Revealed type is "contextlib.nullcontext[None]"
nc.py:8: note: Revealed type is "contextlib.nullcontext[builtins.str]"
nc.py:9: note: Revealed type is "contextlib.nullcontext[builtins.int]"
nc.py:11: note: Revealed type is "contextlib.nullcontext[Any]"
nc.py:12: note: Revealed type is "contextlib.nullcontext[Any]"
nc.py:15: note: Revealed type is "contextlib.nullcontext[builtins.int] | contextlib.nullcontext[None]"
nc.py:16: error: Incompatible types in assignment (expression has type "nullcontext[int | None] | nullcontext[None]", variable has type "nullcontext[int | None]")  [assignment]
Found 1 error in 1 file (checked 1 source file)
$ npx pyright nc.py
nc.py
  nc.py:5:17 - information: Type of "nc()" is "nullcontext[None]"
  nc.py:6:17 - information: Type of "nc(None)" is "nullcontext[None]"
  nc.py:8:17 - information: Type of "nc("")" is "nullcontext[str]"
  nc.py:9:17 - information: Type of "nc(123)" is "nullcontext[int]"
  nc.py:11:17 - information: Type of "nc(a)" is "nullcontext[None]"
  nc.py:12:17 - information: Type of "nc(s[0])" is "nullcontext[None]"
  nc.py:15:17 - information: Type of "nc(o)" is "nullcontext[int | None]"
  nc.py:17:30 - error: Type "nullcontext[int | None]" is not assignable to declared type "nullcontext[int] | nullcontext[None]"
    Type "nullcontext[int | None]" is not assignable to type "nullcontext[int] | nullcontext[None]"
      "nullcontext[int | None]" is not assignable to "nullcontext[int]"
        Type parameter "_T@nullcontext" is invariant, but "int | None" is not the same as "int"
      "nullcontext[int | None]" is not assignable to "nullcontext[None]"
        Type parameter "_T@nullcontext" is invariant, but "int | None" is not the same as "None" (reportAssignmentType)
1 error, 0 warnings, 7 informations

With this patch

$ mypy nc.py --custom-typeshed-dir=../typeshed
nc.py:5: note: Revealed type is "contextlib.nullcontext[None]"
nc.py:6: note: Revealed type is "contextlib.nullcontext[None]"
nc.py:8: note: Revealed type is "contextlib.nullcontext[builtins.str]"
nc.py:9: note: Revealed type is "contextlib.nullcontext[builtins.int]"
nc.py:11: note: Revealed type is "contextlib.nullcontext[Any]"
nc.py:12: note: Revealed type is "contextlib.nullcontext[Any]"
nc.py:15: note: Revealed type is "contextlib.nullcontext[builtins.int | None]"
nc.py:17: error: Incompatible types in assignment (expression has type "nullcontext[int | None]", variable has type "nullcontext[int] | nullcontext[None]")  [assignment]
Found 1 error in 1 file (checked 1 source file)
$ npx pyright nc.py -t ../typeshed
nc.py
  nc.py:5:17 - information: Type of "nc()" is "nullcontext[None]"
  nc.py:6:17 - information: Type of "nc(None)" is "nullcontext[None]"
  nc.py:8:17 - information: Type of "nc("")" is "nullcontext[str]"
  nc.py:9:17 - information: Type of "nc(123)" is "nullcontext[int]"
  nc.py:11:17 - information: Type of "nc(a)" is "nullcontext[Any]"
  nc.py:12:17 - information: Type of "nc(s[0])" is "nullcontext[Unknown]"
  nc.py:15:17 - information: Type of "nc(o)" is "nullcontext[int | None]"
  nc.py:17:30 - error: Type "nullcontext[int | None]" is not assignable to declared type "nullcontext[int] | nullcontext[None]"
    Type "nullcontext[int | None]" is not assignable to type "nullcontext[int] | nullcontext[None]"
      "nullcontext[int | None]" is not assignable to "nullcontext[int]"
        Type parameter "_T@nullcontext" is invariant, but "int | None" is not the same as "int"
      "nullcontext[int | None]" is not assignable to "nullcontext[None]"
        Type parameter "_T@nullcontext" is invariant, but "int | None" is not the same as "None" (reportAssignmentType)
1 error, 0 warnings, 7 informations

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

@pinterior
Copy link
Contributor Author

was originally reported on microsoft/pyright#11304

Copy link
Collaborator

@srittau srittau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@srittau srittau merged commit b0401bc into python:main Mar 4, 2026
51 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants