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]
)
| 330 | |
| 331 | |
| 332 | def 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 | |
| 383 | def is_trivial_bound(tp: ProperType, allow_tuple: bool = False) -> bool: |
no test coverage detected
searching dependent graphs…