Skip to content

Commit e1ff0ed

Browse files
committed
Address review; simplify
1 parent c2dc532 commit e1ff0ed

File tree

2 files changed

+25
-40
lines changed

2 files changed

+25
-40
lines changed

mypy/meet.py

+12-24
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
from itertools import chain
43
from typing import Callable
54

65
from mypy import join
@@ -343,13 +342,20 @@ def _is_overlapping_types(left: Type, right: Type) -> bool:
343342
left_possible = get_possible_variants(left)
344343
right_possible = get_possible_variants(right)
345344

346-
# First handle a special case: comparing a `Parameters` to a `ParamSpecType`.
347-
# This should always be considered an overlapping equality check.
348-
# This needs to be done before we move on to other TypeVarLike comparisons.
349-
if (isinstance(left, Parameters) and isinstance(right, ParamSpecType)) or (
350-
isinstance(left, ParamSpecType) and isinstance(right, Parameters)
345+
# First handle special cases relating to PEP 612:
346+
# - comparing a `Parameters` to a `Parameters
347+
# - comparing a `Parameters` to a `ParamSpecType`
348+
# - comparing a `ParamSpecType` to a `ParamSpecType`
349+
#
350+
# This should all always be considered overlapping equality checks.
351+
# These need to be done before we move on to other TypeVarLike comparisons.
352+
if isinstance(left, (Parameters, ParamSpecType)) and isinstance(
353+
right, (Parameters, ParamSpecType)
351354
):
352355
return True
356+
# A `Parameters` does not overlap with anything else, however
357+
if isinstance(left, Parameters) or isinstance(right, Parameters):
358+
return False
353359

354360
# Now move on to checking multi-variant types like Unions. We also perform
355361
# the same logic if either type happens to be a TypeVar/ParamSpec/TypeVarTuple.
@@ -460,24 +466,6 @@ def _type_object_overlap(left: Type, right: Type) -> bool:
460466
elif isinstance(right, CallableType):
461467
right = right.fallback
462468

463-
if isinstance(left, Parameters):
464-
if not isinstance(right, Parameters):
465-
return False
466-
if len(left.arg_types) == len(right.arg_types):
467-
return all(
468-
_is_overlapping_types(left_arg, right_arg)
469-
for left_arg, right_arg in zip(left.arg_types, right.arg_types)
470-
)
471-
if not any(
472-
isinstance(arg, TypeVarLikeType) for arg in chain(left.arg_types, right.arg_types)
473-
):
474-
return False
475-
# TODO: Is this sound?
476-
return True
477-
if isinstance(right, Parameters):
478-
assert not isinstance(left, (Parameters, TypeVarLikeType))
479-
return False
480-
481469
if isinstance(left, LiteralType) and isinstance(right, LiteralType):
482470
if left.value == right.value:
483471
# If values are the same, we still need to check if fallbacks are overlapping,

test-data/unit/pythoneval.test

+13-16
Original file line numberDiff line numberDiff line change
@@ -1935,38 +1935,35 @@ P = ParamSpec("P")
19351935
class Foo(Generic[P]): ...
19361936
class Bar(Generic[P]): ...
19371937

1938-
def bad1(foo1: Foo[[int]], foo2: Foo[[str]]) -> bool:
1939-
return foo1 == foo2
1938+
def bad(foo: Foo[[int]], bar: Bar[[int]]) -> bool:
1939+
return foo == bar
19401940

1941-
def bad2(foo1: Foo[[int, str]], foo2: Foo[[int, bytes]]) -> bool:
1941+
def good1(foo1: Foo[[int]], foo2: Foo[[str]]) -> bool:
19421942
return foo1 == foo2
19431943

1944-
def bad3(foo1: Foo[[int]], foo2: Foo[[int, int]]) -> bool:
1944+
def good2(foo1: Foo[[int, str]], foo2: Foo[[int, bytes]]) -> bool:
19451945
return foo1 == foo2
19461946

1947-
def bad4(foo: Foo[[int]], bar: Bar[[int]]) -> bool:
1948-
return foo == bar
1947+
def good3(foo1: Foo[[int]], foo2: Foo[[int, int]]) -> bool:
1948+
return foo1 == foo2
19491949

1950-
def good1(foo1: Foo[[int]], foo2: Foo[[int]]) -> bool:
1950+
def good4(foo1: Foo[[int]], foo2: Foo[[int]]) -> bool:
19511951
return foo1 == foo2
19521952

1953-
def good2(foo1: Foo[[int]], foo2: Foo[[bool]]) -> bool:
1953+
def good5(foo1: Foo[[int]], foo2: Foo[[bool]]) -> bool:
19541954
return foo1 == foo2
19551955

1956-
def good3(foo1: Foo[[int, int]], foo2: Foo[[bool, bool]]) -> bool:
1956+
def good6(foo1: Foo[[int, int]], foo2: Foo[[bool, bool]]) -> bool:
19571957
return foo1 == foo2
19581958

1959-
def good4(foo1: Foo[[int]], foo2: Foo[P], *args: P.args, **kwargs: P.kwargs) -> bool:
1959+
def good7(foo1: Foo[[int]], foo2: Foo[P], *args: P.args, **kwargs: P.kwargs) -> bool:
19601960
return foo1 == foo2
19611961

1962-
def good5(foo1: Foo[P], foo2: Foo[[int, str, bytes]], *args: P.args, **kwargs: P.kwargs) -> bool:
1962+
def good8(foo1: Foo[P], foo2: Foo[[int, str, bytes]], *args: P.args, **kwargs: P.kwargs) -> bool:
19631963
return foo1 == foo2
19641964

1965-
def good6(foo1: Foo[Concatenate[int, P]], foo2: Foo[[int, str, bytes]], *args: P.args, **kwargs: P.kwargs) -> bool:
1965+
def good9(foo1: Foo[Concatenate[int, P]], foo2: Foo[[int, str, bytes]], *args: P.args, **kwargs: P.kwargs) -> bool:
19661966
return foo1 == foo2
19671967

19681968
[out]
1969-
_testStrictEqualitywithParamSpec.py:11: error: Non-overlapping equality check (left operand type: "Foo[[int]]", right operand type: "Foo[[str]]")
1970-
_testStrictEqualitywithParamSpec.py:14: error: Non-overlapping equality check (left operand type: "Foo[[int, str]]", right operand type: "Foo[[int, bytes]]")
1971-
_testStrictEqualitywithParamSpec.py:17: error: Non-overlapping equality check (left operand type: "Foo[[int]]", right operand type: "Foo[[int, int]]")
1972-
_testStrictEqualitywithParamSpec.py:20: error: Non-overlapping equality check (left operand type: "Foo[[int]]", right operand type: "Bar[[int]]")
1969+
_testStrictEqualitywithParamSpec.py:11: error: Non-overlapping equality check (left operand type: "Foo[[int]]", right operand type: "Bar[[int]]")

0 commit comments

Comments
 (0)