Avoid ambiguities for constraints inferred from unions during polymorphic inference. Polymorphic inference implicitly relies on assumption that a reverse of a linear constraint is a linear constraint. This is however not true in presence of union types, for example T :> Union[S, int] vs
(cs: list[Constraint])
| 529 | |
| 530 | |
| 531 | def skip_reverse_union_constraints(cs: list[Constraint]) -> list[Constraint]: |
| 532 | """Avoid ambiguities for constraints inferred from unions during polymorphic inference. |
| 533 | |
| 534 | Polymorphic inference implicitly relies on assumption that a reverse of a linear constraint |
| 535 | is a linear constraint. This is however not true in presence of union types, for example |
| 536 | T :> Union[S, int] vs S <: T. Trying to solve such constraints would be detected ambiguous |
| 537 | as (T, S) form a non-linear SCC. However, simply removing the linear part results in a valid |
| 538 | solution T = Union[S, int], S = <free>. A similar scenario is when we get T <: Union[T, int], |
| 539 | such constraints carry no information, and will equally confuse linearity check. |
| 540 | |
| 541 | TODO: a cleaner solution may be to avoid inferring such constraints in first place, but |
| 542 | this would require passing around a flag through all infer_constraints() calls. |
| 543 | """ |
| 544 | reverse_union_cs = set() |
| 545 | for c in cs: |
| 546 | p_target = get_proper_type(c.target) |
| 547 | if isinstance(p_target, UnionType): |
| 548 | for item in p_target.items: |
| 549 | if isinstance(item, TypeVarType): |
| 550 | if item == c.origin_type_var and c.op == SUBTYPE_OF: |
| 551 | reverse_union_cs.add(c) |
| 552 | continue |
| 553 | # These two forms are semantically identical, but are different from |
| 554 | # the point of view of Constraint.__eq__(). |
| 555 | reverse_union_cs.add(Constraint(item, neg_op(c.op), c.origin_type_var)) |
| 556 | reverse_union_cs.add(Constraint(c.origin_type_var, c.op, item)) |
| 557 | return [c for c in cs if c not in reverse_union_cs] |
| 558 | |
| 559 | |
| 560 | def get_vars(target: Type, vars: list[TypeVarId]) -> set[TypeVarId]: |
no test coverage detected
searching dependent graphs…