solve.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. """Type inference constraint solving"""
  2. from __future__ import annotations
  3. from collections import defaultdict
  4. from mypy.constraints import SUPERTYPE_OF, Constraint
  5. from mypy.join import join_types
  6. from mypy.meet import meet_types
  7. from mypy.subtypes import is_subtype
  8. from mypy.types import (
  9. AnyType,
  10. ProperType,
  11. Type,
  12. TypeOfAny,
  13. TypeVarId,
  14. UninhabitedType,
  15. UnionType,
  16. get_proper_type,
  17. )
  18. from mypy.typestate import type_state
  19. def solve_constraints(
  20. vars: list[TypeVarId], constraints: list[Constraint], strict: bool = True
  21. ) -> list[Type | None]:
  22. """Solve type constraints.
  23. Return the best type(s) for type variables; each type can be None if the value of the variable
  24. could not be solved.
  25. If a variable has no constraints, if strict=True then arbitrarily
  26. pick NoneType as the value of the type variable. If strict=False,
  27. pick AnyType.
  28. """
  29. # Collect a list of constraints for each type variable.
  30. cmap: dict[TypeVarId, list[Constraint]] = defaultdict(list)
  31. for con in constraints:
  32. cmap[con.type_var].append(con)
  33. res: list[Type | None] = []
  34. # Solve each type variable separately.
  35. for tvar in vars:
  36. bottom: Type | None = None
  37. top: Type | None = None
  38. candidate: Type | None = None
  39. # Process each constraint separately, and calculate the lower and upper
  40. # bounds based on constraints. Note that we assume that the constraint
  41. # targets do not have constraint references.
  42. for c in cmap.get(tvar, []):
  43. if c.op == SUPERTYPE_OF:
  44. if bottom is None:
  45. bottom = c.target
  46. else:
  47. if type_state.infer_unions:
  48. # This deviates from the general mypy semantics because
  49. # recursive types are union-heavy in 95% of cases.
  50. bottom = UnionType.make_union([bottom, c.target])
  51. else:
  52. bottom = join_types(bottom, c.target)
  53. else:
  54. if top is None:
  55. top = c.target
  56. else:
  57. top = meet_types(top, c.target)
  58. p_top = get_proper_type(top)
  59. p_bottom = get_proper_type(bottom)
  60. if isinstance(p_top, AnyType) or isinstance(p_bottom, AnyType):
  61. source_any = top if isinstance(p_top, AnyType) else bottom
  62. assert isinstance(source_any, ProperType) and isinstance(source_any, AnyType)
  63. res.append(AnyType(TypeOfAny.from_another_any, source_any=source_any))
  64. continue
  65. elif bottom is None:
  66. if top:
  67. candidate = top
  68. else:
  69. # No constraints for type variable -- 'UninhabitedType' is the most specific type.
  70. if strict:
  71. candidate = UninhabitedType()
  72. candidate.ambiguous = True
  73. else:
  74. candidate = AnyType(TypeOfAny.special_form)
  75. elif top is None:
  76. candidate = bottom
  77. elif is_subtype(bottom, top):
  78. candidate = bottom
  79. else:
  80. candidate = None
  81. res.append(candidate)
  82. return res