Skip to content

Commit 7251ef8

Browse files
authored
Delete sametypes.py (#13311)
Fixes #7924 So this is not 100% refactor, I make several semantic changes. As discussed in the issue, current implementation is not very principled, so I replace old complex logic with two options: * New `is_same_types()` is now located in `subtypes.py` and is doing two-way proper subtyping check. * Type equality with `==` can be used when we are checking for representation equality (used rarely, mostly for internal things) Btw this uncovered two actual bugs, one of which I fix here (two-line change), and leave a TODO for the second.
1 parent 5c0377c commit 7251ef8

13 files changed

+45
-276
lines changed

mypy/applytype.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from typing import Callable, Dict, Optional, Sequence
22

3-
import mypy.sametypes
43
import mypy.subtypes
54
from mypy.expandtype import expand_type
65
from mypy.nodes import Context
@@ -41,7 +40,7 @@ def get_target_type(
4140
if isinstance(type, TypeVarType) and type.values:
4241
# Allow substituting T1 for T if every allowed value of T1
4342
# is also a legal value of T.
44-
if all(any(mypy.sametypes.is_same_type(v, v1) for v in values) for v1 in type.values):
43+
if all(any(mypy.subtypes.is_same_type(v, v1) for v in values) for v1 in type.values):
4544
return type
4645
matching = []
4746
for value in values:

mypy/binder.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
from mypy.join import join_simple
99
from mypy.literals import Key, literal, literal_hash, subkeys
1010
from mypy.nodes import AssignmentExpr, Expression, IndexExpr, MemberExpr, NameExpr, RefExpr, Var
11-
from mypy.sametypes import is_same_type
12-
from mypy.subtypes import is_subtype
11+
from mypy.subtypes import is_same_type, is_subtype
1312
from mypy.types import AnyType, NoneType, PartialType, Type, TypeOfAny, UnionType, get_proper_type
1413

1514
BindableExpression: _TypeAlias = Union[IndexExpr, MemberExpr, AssignmentExpr, NameExpr]

mypy/checker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@
133133
)
134134
from mypy.options import Options
135135
from mypy.plugin import CheckerPluginInterface, Plugin
136-
from mypy.sametypes import is_same_type
137136
from mypy.scope import Scope
138137
from mypy.semanal import is_trivial_body, refers_to_fullname, set_callable_name
139138
from mypy.semanal_enum import ENUM_BASES, ENUM_SPECIAL_PROPS
@@ -145,6 +144,7 @@
145144
is_equivalent,
146145
is_more_precise,
147146
is_proper_subtype,
147+
is_same_type,
148148
is_subtype,
149149
restrict_subtype_away,
150150
unify_generic_callable,

mypy/checkexpr.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,9 @@
9595
MethodSigContext,
9696
Plugin,
9797
)
98-
from mypy.sametypes import is_same_type
9998
from mypy.semanal_enum import ENUM_BASES
10099
from mypy.state import state
101-
from mypy.subtypes import is_equivalent, is_subtype, non_method_protocol_members
100+
from mypy.subtypes import is_equivalent, is_same_type, is_subtype, non_method_protocol_members
102101
from mypy.traverser import has_await_expression
103102
from mypy.typeanal import (
104103
check_for_explicit_any,
@@ -3561,7 +3560,7 @@ def visit_cast_expr(self, expr: CastExpr) -> Type:
35613560
if (
35623561
options.warn_redundant_casts
35633562
and not isinstance(get_proper_type(target_type), AnyType)
3564-
and is_same_type(source_type, target_type)
3563+
and source_type == target_type
35653564
):
35663565
self.msg.redundant_cast(target_type, expr)
35673566
if options.disallow_any_unimported and has_any_from_unimported_type(target_type):

mypy/constraints.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@
44

55
from typing_extensions import Final
66

7-
import mypy.sametypes
87
import mypy.subtypes
98
import mypy.typeops
109
from mypy.argmap import ArgTypeExpander
1110
from mypy.erasetype import erase_typevars
1211
from mypy.maptype import map_instance_to_supertype
13-
from mypy.nodes import CONTRAVARIANT, COVARIANT, ArgKind
12+
from mypy.nodes import ARG_OPT, ARG_POS, CONTRAVARIANT, COVARIANT, ArgKind
1413
from mypy.types import (
1514
TUPLE_LIKE_INSTANCE_NAMES,
1615
AnyType,
@@ -141,7 +140,9 @@ def infer_constraints(template: Type, actual: Type, direction: int) -> List[Cons
141140
142141
The constraints are represented as Constraint objects.
143142
"""
144-
if any(get_proper_type(template) == get_proper_type(t) for t in TypeState._inferring):
143+
if any(
144+
get_proper_type(template) == get_proper_type(t) for t in reversed(TypeState._inferring)
145+
):
145146
return []
146147
if isinstance(template, TypeAliasType) and template.is_recursive:
147148
# This case requires special care because it may cause infinite recursion.
@@ -341,7 +342,7 @@ def is_same_constraint(c1: Constraint, c2: Constraint) -> bool:
341342
return (
342343
c1.type_var == c2.type_var
343344
and (c1.op == c2.op or skip_op_check)
344-
and mypy.sametypes.is_same_type(c1.target, c2.target)
345+
and mypy.subtypes.is_same_type(c1.target, c2.target)
345346
)
346347

347348

@@ -474,9 +475,7 @@ def visit_instance(self, template: Instance) -> List[Constraint]:
474475
if isinstance(actual, (CallableType, Overloaded)) and template.type.is_protocol:
475476
if template.type.protocol_members == ["__call__"]:
476477
# Special case: a generic callback protocol
477-
if not any(
478-
mypy.sametypes.is_same_type(template, t) for t in template.type.inferring
479-
):
478+
if not any(template == t for t in template.type.inferring):
480479
template.type.inferring.append(template)
481480
call = mypy.subtypes.find_member(
482481
"__call__", template, actual, is_operator=True
@@ -635,7 +634,7 @@ def visit_instance(self, template: Instance) -> List[Constraint]:
635634
# Note that we use is_protocol_implementation instead of is_subtype
636635
# because some type may be considered a subtype of a protocol
637636
# due to _promote, but still not implement the protocol.
638-
not any(mypy.sametypes.is_same_type(template, t) for t in template.type.inferring)
637+
not any(template == t for t in reversed(template.type.inferring))
639638
and mypy.subtypes.is_protocol_implementation(instance, erased)
640639
):
641640
template.type.inferring.append(template)
@@ -651,7 +650,7 @@ def visit_instance(self, template: Instance) -> List[Constraint]:
651650
and self.direction == SUBTYPE_OF
652651
and
653652
# We avoid infinite recursion for structural subtypes also here.
654-
not any(mypy.sametypes.is_same_type(instance, i) for i in instance.type.inferring)
653+
not any(instance == i for i in reversed(instance.type.inferring))
655654
and mypy.subtypes.is_protocol_implementation(erased, instance)
656655
):
657656
instance.type.inferring.append(instance)
@@ -734,6 +733,8 @@ def visit_callable_type(self, template: CallableType) -> List[Constraint]:
734733
cactual_ps = cactual.param_spec()
735734

736735
if not cactual_ps:
736+
max_prefix_len = len([k for k in cactual.arg_kinds if k in (ARG_POS, ARG_OPT)])
737+
prefix_len = min(prefix_len, max_prefix_len)
737738
res.append(
738739
Constraint(
739740
param_spec.id,

mypy/messages.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@
6262
reverse_builtin_aliases,
6363
)
6464
from mypy.operators import op_methods, op_methods_to_symbols
65-
from mypy.sametypes import is_same_type
6665
from mypy.subtypes import (
6766
IS_CLASS_OR_STATIC,
6867
IS_CLASSVAR,
6968
IS_SETTABLE,
7069
find_member,
7170
get_member_flags,
71+
is_same_type,
7272
is_subtype,
7373
)
7474
from mypy.typeops import separate_union_literals

mypy/sametypes.py

Lines changed: 0 additions & 245 deletions
This file was deleted.

0 commit comments

Comments
 (0)