Solve type constraints. Return the best type(s) for type variables; each type can be None if the value of the variable could not be solved. If a variable has no constraints, if strict=True then arbitrarily pick UninhabitedType as the value of the type variable. If strict=False, pic
(
original_vars: Sequence[TypeVarLikeType],
constraints: list[Constraint],
strict: bool = True,
allow_polymorphic: bool = False,
skip_unsatisfied: bool = False,
)
| 40 | |
| 41 | |
| 42 | def solve_constraints( |
| 43 | original_vars: Sequence[TypeVarLikeType], |
| 44 | constraints: list[Constraint], |
| 45 | strict: bool = True, |
| 46 | allow_polymorphic: bool = False, |
| 47 | skip_unsatisfied: bool = False, |
| 48 | ) -> tuple[list[Type | None], list[TypeVarLikeType]]: |
| 49 | """Solve type constraints. |
| 50 | |
| 51 | Return the best type(s) for type variables; each type can be None if the value of |
| 52 | the variable could not be solved. |
| 53 | |
| 54 | If a variable has no constraints, if strict=True then arbitrarily |
| 55 | pick UninhabitedType as the value of the type variable. If strict=False, pick AnyType. |
| 56 | If allow_polymorphic=True, then use the full algorithm that can potentially return |
| 57 | free type variables in solutions (these require special care when applying). Otherwise, |
| 58 | use a simplified algorithm that just solves each type variable individually if possible. |
| 59 | |
| 60 | The skip_unsatisfied flag matches the same one in applytype.apply_generic_arguments(). |
| 61 | """ |
| 62 | vars = [tv.id for tv in original_vars] |
| 63 | if not vars: |
| 64 | return [], [] |
| 65 | |
| 66 | originals = {tv.id: tv for tv in original_vars} |
| 67 | extra_vars: list[TypeVarId] = [] |
| 68 | # Get additional type variables from generic actuals. |
| 69 | for c in constraints: |
| 70 | extra_vars.extend([v.id for v in c.extra_tvars if v.id not in vars + extra_vars]) |
| 71 | originals.update({v.id: v for v in c.extra_tvars if v.id not in originals}) |
| 72 | |
| 73 | if allow_polymorphic: |
| 74 | # Constraints inferred from unions require special handling in polymorphic inference. |
| 75 | constraints = skip_reverse_union_constraints(constraints) |
| 76 | |
| 77 | # Collect a list of constraints for each type variable. |
| 78 | cmap: dict[TypeVarId, list[Constraint]] = {tv: [] for tv in vars + extra_vars} |
| 79 | for con in constraints: |
| 80 | if con.type_var in vars + extra_vars: |
| 81 | cmap[con.type_var].append(con) |
| 82 | |
| 83 | if allow_polymorphic: |
| 84 | if constraints: |
| 85 | solutions, free_vars = solve_with_dependent( |
| 86 | vars + extra_vars, constraints, vars, originals |
| 87 | ) |
| 88 | else: |
| 89 | solutions = {} |
| 90 | free_vars = [] |
| 91 | else: |
| 92 | solutions = {} |
| 93 | free_vars = [] |
| 94 | for tv, cs in cmap.items(): |
| 95 | if not cs: |
| 96 | continue |
| 97 | lowers = [c.target for c in cs if c.op == SUPERTYPE_OF] |
| 98 | uppers = [c.target for c in cs if c.op == SUBTYPE_OF] |
| 99 | solution = solve_one(lowers, uppers) |
searching dependent graphs…