forked from python/mypy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
testsolve.py
149 lines (128 loc) · 6.23 KB
/
testsolve.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"""Test cases for the constraint solver used in type inference."""
from myunit import Suite, assert_equal
from constraints import SUPERTYPE_OF, SUBTYPE_OF, Constraint
from solve import solve_constraints
from typefixture import TypeFixture
class SolveSuite(Suite):
def __init__(self):
super().__init__()
self.fx = TypeFixture()
def test_empty_input(self):
self.assert_solve([], [], [])
def test_simple_supertype_constraints(self):
self.assert_solve(['T'],
[self.supc(self.fx.t, self.fx.a)],
[(self.fx.a, self.fx.o)])
self.assert_solve(['T'],
[self.supc(self.fx.t, self.fx.a),
self.supc(self.fx.t, self.fx.b)],
[(self.fx.a, self.fx.o)])
def test_simple_subtype_constraints(self):
self.assert_solve(['T'],
[self.subc(self.fx.t, self.fx.a)],
[(self.fx.nonet, self.fx.a)])
self.assert_solve(['T'],
[self.subc(self.fx.t, self.fx.a),
self.subc(self.fx.t, self.fx.b)],
[(self.fx.nonet, self.fx.b)])
def test_both_kinds_of_constraints(self):
self.assert_solve(['T'],
[self.supc(self.fx.t, self.fx.b),
self.subc(self.fx.t, self.fx.a)],
[(self.fx.b, self.fx.a)])
def test_unsatisfiable_constraints(self):
# The constraints are impossible to satisfy.
self.assert_solve(['T'],
[self.supc(self.fx.t, self.fx.a),
self.subc(self.fx.t, self.fx.b)],
[None])
def test_exactly_specified_result(self):
self.assert_solve(['T'],
[self.supc(self.fx.t, self.fx.b),
self.subc(self.fx.t, self.fx.b)],
[(self.fx.b, self.fx.b)])
def test_multiple_variables(self):
self.assert_solve(['T', 'S'],
[self.supc(self.fx.t, self.fx.b),
self.supc(self.fx.s, self.fx.c),
self.subc(self.fx.t, self.fx.a)],
[(self.fx.b, self.fx.a), (self.fx.c, self.fx.o)])
def test_no_constraints_for_var(self):
self.assert_solve(['T'],
[],
[(self.fx.nonet, self.fx.o)])
self.assert_solve(['T', 'S'],
[],
[(self.fx.nonet, self.fx.o),
(self.fx.nonet, self.fx.o)])
self.assert_solve(['T', 'S'],
[self.supc(self.fx.s, self.fx.a)],
[(self.fx.nonet, self.fx.o), (self.fx.a, self.fx.o)])
def test_void_constraints(self):
self.assert_solve(['T'],
[self.supc(self.fx.t, self.fx.void)],
[(self.fx.void, self.fx.void)])
self.assert_solve(['T'],
[self.subc(self.fx.t, self.fx.void)],
[(self.fx.void, self.fx.void)])
# Both bounds void.
self.assert_solve(['T'],
[self.supc(self.fx.t, self.fx.void),
self.subc(self.fx.t, self.fx.void)],
[(self.fx.void, self.fx.void)])
# Cannot infer any type.
self.assert_solve(['T'],
[self.supc(self.fx.t, self.fx.a),
self.supc(self.fx.t, self.fx.void)],
[None])
self.assert_solve(['T'],
[self.subc(self.fx.t, self.fx.a),
self.subc(self.fx.t, self.fx.void)],
[None])
def test_simple_constraints_with_dynamic_type(self):
self.assert_solve(['T'],
[self.supc(self.fx.t, self.fx.anyt)],
[(self.fx.anyt, self.fx.anyt)])
self.assert_solve(['T'],
[self.supc(self.fx.t, self.fx.anyt),
self.supc(self.fx.t, self.fx.anyt)],
[(self.fx.anyt, self.fx.anyt)])
self.assert_solve(['T'],
[self.supc(self.fx.t, self.fx.anyt),
self.supc(self.fx.t, self.fx.a)],
[(self.fx.anyt, self.fx.anyt)])
self.assert_solve(['T'],
[self.subc(self.fx.t, self.fx.anyt)],
[(self.fx.anyt, self.fx.anyt)])
self.assert_solve(['T'],
[self.subc(self.fx.t, self.fx.anyt),
self.subc(self.fx.t, self.fx.anyt)],
[(self.fx.anyt, self.fx.anyt)])
self.assert_solve(['T'],
[self.subc(self.fx.t, self.fx.anyt),
self.subc(self.fx.t, self.fx.a)],
[(self.fx.anyt, self.fx.anyt)])
def test_both_normal_and_any_types_in_results(self):
# If one of the bounds is any, we promote the other bound to
# any as well, since otherwise the type range does not make sense.
self.assert_solve(['T'],
[self.supc(self.fx.t, self.fx.a),
self.subc(self.fx.t, self.fx.anyt)],
[(self.fx.anyt, self.fx.anyt)])
self.assert_solve(['T'],
[self.supc(self.fx.t, self.fx.anyt),
self.subc(self.fx.t, self.fx.a)],
[(self.fx.anyt, self.fx.anyt)])
def assert_solve(self, vars, constraints, results):
res = []
for r in results:
if isinstance(r, tuple):
res.append(r[0])
else:
res.append(r)
actual = solve_constraints(vars, constraints, self.fx.basic)
assert_equal(str(actual), str(res))
def supc(self, type_var, bound):
return Constraint(type_var.name, SUPERTYPE_OF, bound)
def subc(self, type_var, bound):
return Constraint(type_var.name, SUBTYPE_OF, bound)