MCPcopy Index your code
hub / github.com/python/mypy / choose_free

Function choose_free

mypy/solve.py:332–380  ·  view source on GitHub ↗

Choose the best solution for an SCC containing only type variables. This is needed to preserve e.g. the upper bound in a situation like this: def dec(f: Callable[[T], S]) -> Callable[[T], S]: ... @dec def test(x: U) -> U: ... where U <: A.

(
    scc: list[TypeVarLikeType], original_vars: list[TypeVarId]
)

Source from the content-addressed store, hash-verified

330
331
332def choose_free(
333 scc: list[TypeVarLikeType], original_vars: list[TypeVarId]
334) -> TypeVarLikeType | None:
335 """Choose the best solution for an SCC containing only type variables.
336
337 This is needed to preserve e.g. the upper bound in a situation like this:
338 def dec(f: Callable[[T], S]) -> Callable[[T], S]: ...
339
340 @dec
341 def test(x: U) -> U: ...
342
343 where U <: A.
344 """
345
346 if len(scc) == 1:
347 # Fast path, choice is trivial.
348 return scc[0]
349
350 common_upper_bound = meet_type_list([t.upper_bound for t in scc])
351 common_upper_bound_p = get_proper_type(common_upper_bound)
352 # We include None for when strict-optional is disabled.
353 if isinstance(common_upper_bound_p, (UninhabitedType, NoneType)):
354 # This will cause to infer Never, which is better than a free TypeVar
355 # that has an upper bound Never.
356 return None
357
358 values: list[Type] = []
359 for tv in scc:
360 if isinstance(tv, TypeVarType) and tv.values:
361 if values:
362 # It is too tricky to support multiple TypeVars with values
363 # within the same SCC.
364 return None
365 values = tv.values.copy()
366
367 if values and not is_trivial_bound(common_upper_bound_p):
368 # If there are both values and upper bound present, we give up,
369 # since type variables having both are not supported.
370 return None
371
372 # For convenience with current type application machinery, we use a stable
373 # choice that prefers the original type variables (not polymorphic ones) in SCC.
374 best = min(scc, key=lambda x: (x.id not in original_vars, x.id.raw_id))
375 if isinstance(best, TypeVarType):
376 return best.copy_modified(values=values, upper_bound=common_upper_bound)
377 if is_trivial_bound(common_upper_bound_p, allow_tuple=True):
378 # TODO: support more cases for ParamSpecs/TypeVarTuples
379 return best
380 return None
381
382
383def is_trivial_bound(tp: ProperType, allow_tuple: bool = False) -> bool:

Callers 1

solve_with_dependentFunction · 0.85

Calls 8

meet_type_listFunction · 0.90
get_proper_typeFunction · 0.90
lenFunction · 0.85
isinstanceFunction · 0.85
is_trivial_boundFunction · 0.85
minFunction · 0.85
copyMethod · 0.45
copy_modifiedMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…