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

Skip to content

Commit b9ea575

Browse files
committed
Refactoring subtyping
1 parent 554db28 commit b9ea575

7 files changed

Lines changed: 121 additions & 112 deletions

File tree

mypy/checker.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@
2929
import mypy.checkexpr
3030
from mypy import messages
3131
from mypy.subtypes import (
32-
is_subtype, is_equivalent, map_instance_to_supertype, is_proper_subtype,
32+
is_subtype, is_equivalent, is_proper_subtype,
3333
is_more_precise, restrict_subtype_away
3434
)
35+
from mypy.maptype import map_instance_to_supertype
3536
from mypy.semanal import self_type, set_callable_name, refers_to_fullname
3637
from mypy.erasetype import erase_typevars
3738
from mypy.expandtype import expand_type_by_instance, expand_type

mypy/checkmember.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from mypy.nodes import TypeInfo, FuncBase, Var, FuncDef, SymbolNode, Context
1010
from mypy.nodes import ARG_POS, function_type, Decorator
1111
from mypy.messages import MessageBuilder
12-
from mypy.subtypes import map_instance_to_supertype
12+
from mypy.maptype import map_instance_to_supertype
1313
from mypy.expandtype import expand_type_by_instance
1414
from mypy.nodes import method_type
1515
from mypy.semanal import self_type

mypy/constraints.py

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

55
from mypy.types import (
66
Callable, Type, TypeVisitor, UnboundType, AnyType, Void, NoneTyp, TypeVar,
7-
Instance, TupleType, UnionType, Overloaded, ErasedType
7+
Instance, TupleType, UnionType, Overloaded, ErasedType, is_named_instance
88
)
99
from mypy.expandtype import expand_caller_var_args
10-
from mypy.subtypes import map_instance_to_supertype, is_named_instance
10+
from mypy.maptype import map_instance_to_supertype
1111
from mypy import nodes
1212

1313

mypy/join.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
ErrorType, TypeVar, Callable, TupleType, ErasedType, TypeList,
88
UnionType, FunctionLike
99
)
10-
from mypy.subtypes import is_subtype, is_equivalent, map_instance_to_supertype
10+
from mypy.maptype import map_instance_to_supertype
11+
from mypy.subtypes import is_subtype, is_equivalent
1112

1213

1314
def join_simple(declaration: Type, s: Type, t: Type) -> Type:

mypy/maptype.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
from typing import Dict, List, cast
2+
3+
from mypy.expandtype import expand_type
4+
from mypy.nodes import TypeInfo
5+
from mypy.types import Type, Instance, AnyType
6+
7+
8+
def map_instance_to_supertype(instance: Instance,
9+
supertype: TypeInfo) -> Instance:
10+
"""Map an Instance type, including the type arguments, to compatible
11+
Instance of a specific supertype.
12+
13+
Assume that supertype is a supertype of instance.type.
14+
"""
15+
if instance.type == supertype:
16+
return instance
17+
18+
# Strip type variables away if the supertype has none.
19+
if not supertype.type_vars:
20+
return Instance(supertype, [])
21+
22+
return map_instance_to_supertypes(instance, supertype)[0]
23+
24+
25+
def map_instance_to_direct_supertype(instance: Instance,
26+
supertype: TypeInfo) -> Instance:
27+
typ = instance.type
28+
29+
for base in typ.bases:
30+
if base.type == supertype:
31+
map = type_var_map(typ, instance.args)
32+
return cast(Instance, expand_type(base, map))
33+
34+
# Relationship with the supertype not specified explicitly. Use AnyType
35+
# type arguments implicitly.
36+
# TODO Should this be an error instead?
37+
return Instance(supertype, [AnyType()] * len(supertype.type_vars))
38+
39+
40+
def type_var_map(typ: TypeInfo, args: List[Type]) -> Dict[int, Type]:
41+
if not args:
42+
return None
43+
else:
44+
tvars = {} # type: Dict[int, Type]
45+
for i in range(len(args)):
46+
tvars[i + 1] = args[i]
47+
return tvars
48+
49+
50+
def map_instance_to_supertypes(instance: Instance,
51+
supertype: TypeInfo) -> List[Instance]:
52+
# FIX: Currently we should only have one supertype per interface, so no
53+
# need to return an array
54+
result = [] # type: List[Instance]
55+
for path in class_derivation_paths(instance.type, supertype):
56+
types = [instance]
57+
for sup in path:
58+
a = [] # type: List[Instance]
59+
for t in types:
60+
a.extend(map_instance_to_direct_supertypes(t, sup))
61+
types = a
62+
result.extend(types)
63+
return result
64+
65+
66+
def class_derivation_paths(typ: TypeInfo,
67+
supertype: TypeInfo) -> List[List[TypeInfo]]:
68+
"""Return an array of non-empty paths of direct base classes from
69+
type to supertype. Return [] if no such path could be found.
70+
71+
InterfaceImplementationPaths(A, B) == [[B]] if A inherits B
72+
InterfaceImplementationPaths(A, C) == [[B, C]] if A inherits B and
73+
B inherits C
74+
"""
75+
# FIX: Currently we might only ever have a single path, so this could be
76+
# simplified
77+
result = [] # type: List[List[TypeInfo]]
78+
79+
for base in typ.bases:
80+
if base.type == supertype:
81+
result.append([base.type])
82+
else:
83+
# Try constructing a longer path via the base class.
84+
for path in class_derivation_paths(base.type, supertype):
85+
result.append([base.type] + path)
86+
87+
return result
88+
89+
90+
def map_instance_to_direct_supertypes(instance: Instance,
91+
supertype: TypeInfo) -> List[Instance]:
92+
# FIX: There should only be one supertypes, always.
93+
typ = instance.type
94+
result = [] # type: List[Instance]
95+
96+
for b in typ.bases:
97+
if b.type == supertype:
98+
map = type_var_map(typ, instance.args)
99+
result.append(cast(Instance, expand_type(b, map)))
100+
101+
if result:
102+
return result
103+
else:
104+
# Relationship with the supertype not specified explicitly. Use dynamic
105+
# type arguments implicitly.
106+
return [Instance(supertype, [AnyType()] * len(supertype.type_vars))]

mypy/subtypes.py

Lines changed: 3 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
from mypy.types import (
44
Type, AnyType, UnboundType, TypeVisitor, ErrorType, Void, NoneTyp,
5-
Instance, TypeVar, Callable, TupleType, UnionType, Overloaded, ErasedType, TypeList
5+
Instance, TypeVar, Callable, TupleType, UnionType, Overloaded, ErasedType, TypeList,
6+
is_named_instance
67
)
78
from mypy import sametypes
89
from mypy.nodes import TypeInfo
910
from mypy.expandtype import expand_type
11+
from mypy.maptype import map_instance_to_supertype
1012

1113

1214
def is_immutable(t: Instance) -> bool:
@@ -190,112 +192,6 @@ def is_callable_subtype(left: Callable, right: Callable) -> bool:
190192
return True
191193

192194

193-
def map_instance_to_supertype(instance: Instance,
194-
supertype: TypeInfo) -> Instance:
195-
"""Map an Instance type, including the type arguments, to compatible
196-
Instance of a specific supertype.
197-
198-
Assume that supertype is a supertype of instance.type.
199-
"""
200-
if instance.type == supertype:
201-
return instance
202-
203-
# Strip type variables away if the supertype has none.
204-
if not supertype.type_vars:
205-
return Instance(supertype, [])
206-
207-
return map_instance_to_supertypes(instance, supertype)[0]
208-
209-
210-
def map_instance_to_direct_supertype(instance: Instance,
211-
supertype: TypeInfo) -> Instance:
212-
typ = instance.type
213-
214-
for base in typ.bases:
215-
if base.type == supertype:
216-
map = type_var_map(typ, instance.args)
217-
return cast(Instance, expand_type(base, map))
218-
219-
# Relationship with the supertype not specified explicitly. Use AnyType
220-
# type arguments implicitly.
221-
# TODO Should this be an error instead?
222-
return Instance(supertype, [AnyType()] * len(supertype.type_vars))
223-
224-
225-
def type_var_map(typ: TypeInfo, args: List[Type]) -> Dict[int, Type]:
226-
if not args:
227-
return None
228-
else:
229-
tvars = {} # type: Dict[int, Type]
230-
for i in range(len(args)):
231-
tvars[i + 1] = args[i]
232-
return tvars
233-
234-
235-
def map_instance_to_supertypes(instance: Instance,
236-
supertype: TypeInfo) -> List[Instance]:
237-
# FIX: Currently we should only have one supertype per interface, so no
238-
# need to return an array
239-
result = [] # type: List[Instance]
240-
for path in class_derivation_paths(instance.type, supertype):
241-
types = [instance]
242-
for sup in path:
243-
a = [] # type: List[Instance]
244-
for t in types:
245-
a.extend(map_instance_to_direct_supertypes(t, sup))
246-
types = a
247-
result.extend(types)
248-
return result
249-
250-
251-
def class_derivation_paths(typ: TypeInfo,
252-
supertype: TypeInfo) -> List[List[TypeInfo]]:
253-
"""Return an array of non-empty paths of direct base classes from
254-
type to supertype. Return [] if no such path could be found.
255-
256-
InterfaceImplementationPaths(A, B) == [[B]] if A inherits B
257-
InterfaceImplementationPaths(A, C) == [[B, C]] if A inherits B and
258-
B inherits C
259-
"""
260-
# FIX: Currently we might only ever have a single path, so this could be
261-
# simplified
262-
result = [] # type: List[List[TypeInfo]]
263-
264-
for base in typ.bases:
265-
if base.type == supertype:
266-
result.append([base.type])
267-
else:
268-
# Try constructing a longer path via the base class.
269-
for path in class_derivation_paths(base.type, supertype):
270-
result.append([base.type] + path)
271-
272-
return result
273-
274-
275-
def map_instance_to_direct_supertypes(instance: Instance,
276-
supertype: TypeInfo) -> List[Instance]:
277-
# FIX: There should only be one supertypes, always.
278-
typ = instance.type
279-
result = [] # type: List[Instance]
280-
281-
for b in typ.bases:
282-
if b.type == supertype:
283-
map = type_var_map(typ, instance.args)
284-
result.append(cast(Instance, expand_type(b, map)))
285-
286-
if result:
287-
return result
288-
else:
289-
# Relationship with the supertype not specified explicitly. Use dynamic
290-
# type arguments implicitly.
291-
return [Instance(supertype, [AnyType()] * len(supertype.type_vars))]
292-
293-
294-
def is_named_instance(t: Type, fullname: str) -> bool:
295-
return (isinstance(t, Instance) and
296-
cast(Instance, t).type.fullname() == fullname)
297-
298-
299195
def restrict_subtype_away(t: Type, s: Type) -> Type:
300196
"""Return a supertype of (t intersect not s)
301197

mypy/types.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,3 +827,8 @@ def replace_leading_arg_type(t: Callable, self_type: Type) -> Callable:
827827
t.variables,
828828
t.bound_vars,
829829
t.line, None)
830+
831+
832+
def is_named_instance(t: Type, fullname: str) -> bool:
833+
return (isinstance(t, Instance) and
834+
cast(Instance, t).type.fullname() == fullname)

0 commit comments

Comments
 (0)