|
3 | 3 | from __future__ import annotations
|
4 | 4 |
|
5 | 5 | from collections.abc import Iterable, Sequence
|
6 |
| -from typing import TYPE_CHECKING, Final, cast |
| 6 | +from typing import Final, cast |
7 | 7 | from typing_extensions import TypeGuard
|
8 | 8 |
|
9 | 9 | import mypy.subtypes
|
10 | 10 | import mypy.typeops
|
11 |
| -from mypy.argmap import ArgTypeExpander |
12 | 11 | from mypy.erasetype import erase_typevars
|
13 | 12 | from mypy.maptype import map_instance_to_supertype
|
14 |
| -from mypy.nodes import ( |
15 |
| - ARG_OPT, |
16 |
| - ARG_POS, |
17 |
| - ARG_STAR, |
18 |
| - ARG_STAR2, |
19 |
| - CONTRAVARIANT, |
20 |
| - COVARIANT, |
21 |
| - ArgKind, |
22 |
| - TypeInfo, |
23 |
| -) |
| 13 | +from mypy.nodes import ARG_OPT, ARG_POS, ARG_STAR, ARG_STAR2, CONTRAVARIANT, COVARIANT, TypeInfo |
24 | 14 | from mypy.types import (
|
25 | 15 | TUPLE_LIKE_INSTANCE_NAMES,
|
26 | 16 | AnyType,
|
|
63 | 53 | from mypy.types_utils import is_union_with_any
|
64 | 54 | from mypy.typestate import type_state
|
65 | 55 |
|
66 |
| -if TYPE_CHECKING: |
67 |
| - from mypy.infer import ArgumentInferContext |
68 |
| - |
69 | 56 | SUBTYPE_OF: Final = 0
|
70 | 57 | SUPERTYPE_OF: Final = 1
|
71 | 58 |
|
@@ -107,175 +94,6 @@ def __eq__(self, other: object) -> bool:
|
107 | 94 | return (self.type_var, self.op, self.target) == (other.type_var, other.op, other.target)
|
108 | 95 |
|
109 | 96 |
|
110 |
| -def infer_constraints_for_callable( |
111 |
| - callee: CallableType, |
112 |
| - arg_types: Sequence[Type | None], |
113 |
| - arg_kinds: list[ArgKind], |
114 |
| - arg_names: Sequence[str | None] | None, |
115 |
| - formal_to_actual: list[list[int]], |
116 |
| - context: ArgumentInferContext, |
117 |
| -) -> list[Constraint]: |
118 |
| - """Infer type variable constraints for a callable and actual arguments. |
119 |
| -
|
120 |
| - Return a list of constraints. |
121 |
| - """ |
122 |
| - constraints: list[Constraint] = [] |
123 |
| - mapper = ArgTypeExpander(context) |
124 |
| - |
125 |
| - param_spec = callee.param_spec() |
126 |
| - param_spec_arg_types = [] |
127 |
| - param_spec_arg_names = [] |
128 |
| - param_spec_arg_kinds = [] |
129 |
| - |
130 |
| - incomplete_star_mapping = False |
131 |
| - for i, actuals in enumerate(formal_to_actual): # TODO: isn't this `enumerate(arg_types)`? |
132 |
| - for actual in actuals: |
133 |
| - if actual is None and callee.arg_kinds[i] in (ARG_STAR, ARG_STAR2): # type: ignore[unreachable] |
134 |
| - # We can't use arguments to infer ParamSpec constraint, if only some |
135 |
| - # are present in the current inference pass. |
136 |
| - incomplete_star_mapping = True # type: ignore[unreachable] |
137 |
| - break |
138 |
| - |
139 |
| - for i, actuals in enumerate(formal_to_actual): |
140 |
| - if isinstance(callee.arg_types[i], UnpackType): |
141 |
| - unpack_type = callee.arg_types[i] |
142 |
| - assert isinstance(unpack_type, UnpackType) |
143 |
| - |
144 |
| - # In this case we are binding all the actuals to *args, |
145 |
| - # and we want a constraint that the typevar tuple being unpacked |
146 |
| - # is equal to a type list of all the actuals. |
147 |
| - actual_types = [] |
148 |
| - |
149 |
| - unpacked_type = get_proper_type(unpack_type.type) |
150 |
| - if isinstance(unpacked_type, TypeVarTupleType): |
151 |
| - tuple_instance = unpacked_type.tuple_fallback |
152 |
| - elif isinstance(unpacked_type, TupleType): |
153 |
| - tuple_instance = unpacked_type.partial_fallback |
154 |
| - else: |
155 |
| - assert False, "mypy bug: unhandled constraint inference case" |
156 |
| - |
157 |
| - for actual in actuals: |
158 |
| - actual_arg_type = arg_types[actual] |
159 |
| - if actual_arg_type is None: |
160 |
| - continue |
161 |
| - |
162 |
| - expanded_actual = mapper.expand_actual_type( |
163 |
| - actual_arg_type, |
164 |
| - arg_kinds[actual], |
165 |
| - callee.arg_names[i], |
166 |
| - callee.arg_kinds[i], |
167 |
| - allow_unpack=True, |
168 |
| - ) |
169 |
| - |
170 |
| - if arg_kinds[actual] != ARG_STAR or isinstance( |
171 |
| - get_proper_type(actual_arg_type), TupleType |
172 |
| - ): |
173 |
| - actual_types.append(expanded_actual) |
174 |
| - else: |
175 |
| - # If we are expanding an iterable inside * actual, append a homogeneous item instead |
176 |
| - actual_types.append( |
177 |
| - UnpackType(tuple_instance.copy_modified(args=[expanded_actual])) |
178 |
| - ) |
179 |
| - |
180 |
| - if isinstance(unpacked_type, TypeVarTupleType): |
181 |
| - constraints.append( |
182 |
| - Constraint( |
183 |
| - unpacked_type, |
184 |
| - SUPERTYPE_OF, |
185 |
| - TupleType(actual_types, unpacked_type.tuple_fallback), |
186 |
| - ) |
187 |
| - ) |
188 |
| - elif isinstance(unpacked_type, TupleType): |
189 |
| - # Prefixes get converted to positional args, so technically the only case we |
190 |
| - # should have here is like Tuple[Unpack[Ts], Y1, Y2, Y3]. If this turns out |
191 |
| - # not to hold we can always handle the prefixes too. |
192 |
| - inner_unpack = unpacked_type.items[0] |
193 |
| - assert isinstance(inner_unpack, UnpackType) |
194 |
| - inner_unpacked_type = get_proper_type(inner_unpack.type) |
195 |
| - suffix_len = len(unpacked_type.items) - 1 |
196 |
| - if isinstance(inner_unpacked_type, TypeVarTupleType): |
197 |
| - # Variadic item can be either *Ts... |
198 |
| - constraints.append( |
199 |
| - Constraint( |
200 |
| - inner_unpacked_type, |
201 |
| - SUPERTYPE_OF, |
202 |
| - TupleType( |
203 |
| - actual_types[:-suffix_len], inner_unpacked_type.tuple_fallback |
204 |
| - ), |
205 |
| - ) |
206 |
| - ) |
207 |
| - else: |
208 |
| - # ...or it can be a homogeneous tuple. |
209 |
| - assert ( |
210 |
| - isinstance(inner_unpacked_type, Instance) |
211 |
| - and inner_unpacked_type.type.fullname == "builtins.tuple" |
212 |
| - ) |
213 |
| - for at in actual_types[:-suffix_len]: |
214 |
| - constraints.extend( |
215 |
| - infer_constraints(inner_unpacked_type.args[0], at, SUPERTYPE_OF) |
216 |
| - ) |
217 |
| - # Now handle the suffix (if any). |
218 |
| - if suffix_len: |
219 |
| - for tt, at in zip(unpacked_type.items[1:], actual_types[-suffix_len:]): |
220 |
| - constraints.extend(infer_constraints(tt, at, SUPERTYPE_OF)) |
221 |
| - else: |
222 |
| - assert False, "mypy bug: unhandled constraint inference case" |
223 |
| - else: |
224 |
| - for actual in actuals: |
225 |
| - actual_arg_type = arg_types[actual] |
226 |
| - if actual_arg_type is None: |
227 |
| - continue |
228 |
| - |
229 |
| - if param_spec and callee.arg_kinds[i] in (ARG_STAR, ARG_STAR2): |
230 |
| - # If actual arguments are mapped to ParamSpec type, we can't infer individual |
231 |
| - # constraints, instead store them and infer single constraint at the end. |
232 |
| - # It is impossible to map actual kind to formal kind, so use some heuristic. |
233 |
| - # This inference is used as a fallback, so relying on heuristic should be OK. |
234 |
| - if not incomplete_star_mapping: |
235 |
| - param_spec_arg_types.append( |
236 |
| - mapper.expand_actual_type( |
237 |
| - actual_arg_type, arg_kinds[actual], None, arg_kinds[actual] |
238 |
| - ) |
239 |
| - ) |
240 |
| - actual_kind = arg_kinds[actual] |
241 |
| - param_spec_arg_kinds.append( |
242 |
| - ARG_POS if actual_kind not in (ARG_STAR, ARG_STAR2) else actual_kind |
243 |
| - ) |
244 |
| - param_spec_arg_names.append(arg_names[actual] if arg_names else None) |
245 |
| - else: |
246 |
| - actual_type = mapper.expand_actual_type( |
247 |
| - actual_arg_type, |
248 |
| - arg_kinds[actual], |
249 |
| - callee.arg_names[i], |
250 |
| - callee.arg_kinds[i], |
251 |
| - ) |
252 |
| - c = infer_constraints(callee.arg_types[i], actual_type, SUPERTYPE_OF) |
253 |
| - constraints.extend(c) |
254 |
| - if ( |
255 |
| - param_spec |
256 |
| - and not any(c.type_var == param_spec.id for c in constraints) |
257 |
| - and not incomplete_star_mapping |
258 |
| - ): |
259 |
| - # Use ParamSpec constraint from arguments only if there are no other constraints, |
260 |
| - # since as explained above it is quite ad-hoc. |
261 |
| - constraints.append( |
262 |
| - Constraint( |
263 |
| - param_spec, |
264 |
| - SUPERTYPE_OF, |
265 |
| - Parameters( |
266 |
| - arg_types=param_spec_arg_types, |
267 |
| - arg_kinds=param_spec_arg_kinds, |
268 |
| - arg_names=param_spec_arg_names, |
269 |
| - imprecise_arg_kinds=True, |
270 |
| - ), |
271 |
| - ) |
272 |
| - ) |
273 |
| - if any(isinstance(v, ParamSpecType) for v in callee.variables): |
274 |
| - # As a perf optimization filter imprecise constraints only when we can have them. |
275 |
| - constraints = filter_imprecise_kinds(constraints) |
276 |
| - return constraints |
277 |
| - |
278 |
| - |
279 | 97 | def infer_constraints(
|
280 | 98 | template: Type, actual: Type, direction: int, skip_neg_op: bool = False
|
281 | 99 | ) -> list[Constraint]:
|
|
0 commit comments