From 831c28219432e0e0371029ae61956f159c32e949 Mon Sep 17 00:00:00 2001 From: subotac <73706465+subotac@users.noreply.github.com> Date: Fri, 31 Jul 2026 21:17:38 +0300 Subject: [PATCH] Fix set xor return types for abstract sets --- stdlib/@tests/test_cases/builtins/check_set.py | 8 ++++++++ stdlib/builtins.pyi | 14 ++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/stdlib/@tests/test_cases/builtins/check_set.py b/stdlib/@tests/test_cases/builtins/check_set.py index 89cb8683bfe1..0cd429299ea5 100644 --- a/stdlib/@tests/test_cases/builtins/check_set.py +++ b/stdlib/@tests/test_cases/builtins/check_set.py @@ -1,3 +1,4 @@ +from collections.abc import Set as AbstractSet from typing_extensions import Literal, assert_type @@ -55,3 +56,10 @@ def test_frozenset_interface(s: frozenset[Literal["foo", "bar"]], y: frozenset[s assert_type(s & y, frozenset[Literal["foo", "bar"]]) assert_type(s | y, frozenset[str]) assert_type(s ^ y, frozenset[str]) + + +def test_xor_with_abstract_set( + s: set[Literal["foo", "bar"]], frozen: frozenset[Literal["foo", "bar"]], other: AbstractSet[str] +) -> None: + assert_type(s ^ other, AbstractSet[str]) + assert_type(frozen ^ other, AbstractSet[str]) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 3c549d97316c..16c4a06062ba 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -1460,7 +1460,12 @@ class set(MutableSet[_T]): def __ior__(self, value: AbstractSet[_T], /) -> Self: ... # type: ignore[override,misc] def __sub__(self, value: AbstractSet[object], /) -> set[_T]: ... def __isub__(self, value: AbstractSet[object], /) -> Self: ... - def __xor__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ... + + @overload + def __xor__(self, value: set[_S] | frozenset[_S], /) -> set[_T | _S]: ... + @overload + def __xor__(self, value: AbstractSet[_S], /) -> AbstractSet[_T | _S]: ... + def __ixor__(self, value: AbstractSet[_T], /) -> Self: ... # type: ignore[override,misc] def __le__(self, value: AbstractSet[object], /) -> bool: ... def __lt__(self, value: AbstractSet[object], /) -> bool: ... @@ -1491,7 +1496,12 @@ class frozenset(AbstractSet[_T_co]): def __and__(self, value: AbstractSet[object], /) -> frozenset[_T_co]: ... def __or__(self, value: AbstractSet[_S], /) -> frozenset[_T_co | _S]: ... def __sub__(self, value: AbstractSet[object], /) -> frozenset[_T_co]: ... - def __xor__(self, value: AbstractSet[_S], /) -> frozenset[_T_co | _S]: ... + + @overload + def __xor__(self, value: set[_S] | frozenset[_S], /) -> frozenset[_T_co | _S]: ... + @overload + def __xor__(self, value: AbstractSet[_S], /) -> AbstractSet[_T_co | _S]: ... + def __le__(self, value: AbstractSet[object], /) -> bool: ... def __lt__(self, value: AbstractSet[object], /) -> bool: ... def __ge__(self, value: AbstractSet[object], /) -> bool: ...