|
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