testsolve.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. """Test cases for the constraint solver used in type inference."""
  2. from __future__ import annotations
  3. from mypy.constraints import SUBTYPE_OF, SUPERTYPE_OF, Constraint
  4. from mypy.solve import solve_constraints
  5. from mypy.test.helpers import Suite, assert_equal
  6. from mypy.test.typefixture import TypeFixture
  7. from mypy.types import Type, TypeVarId, TypeVarType
  8. class SolveSuite(Suite):
  9. def setUp(self) -> None:
  10. self.fx = TypeFixture()
  11. def test_empty_input(self) -> None:
  12. self.assert_solve([], [], [])
  13. def test_simple_supertype_constraints(self) -> None:
  14. self.assert_solve(
  15. [self.fx.t.id], [self.supc(self.fx.t, self.fx.a)], [(self.fx.a, self.fx.o)]
  16. )
  17. self.assert_solve(
  18. [self.fx.t.id],
  19. [self.supc(self.fx.t, self.fx.a), self.supc(self.fx.t, self.fx.b)],
  20. [(self.fx.a, self.fx.o)],
  21. )
  22. def test_simple_subtype_constraints(self) -> None:
  23. self.assert_solve([self.fx.t.id], [self.subc(self.fx.t, self.fx.a)], [self.fx.a])
  24. self.assert_solve(
  25. [self.fx.t.id],
  26. [self.subc(self.fx.t, self.fx.a), self.subc(self.fx.t, self.fx.b)],
  27. [self.fx.b],
  28. )
  29. def test_both_kinds_of_constraints(self) -> None:
  30. self.assert_solve(
  31. [self.fx.t.id],
  32. [self.supc(self.fx.t, self.fx.b), self.subc(self.fx.t, self.fx.a)],
  33. [(self.fx.b, self.fx.a)],
  34. )
  35. def test_unsatisfiable_constraints(self) -> None:
  36. # The constraints are impossible to satisfy.
  37. self.assert_solve(
  38. [self.fx.t.id],
  39. [self.supc(self.fx.t, self.fx.a), self.subc(self.fx.t, self.fx.b)],
  40. [None],
  41. )
  42. def test_exactly_specified_result(self) -> None:
  43. self.assert_solve(
  44. [self.fx.t.id],
  45. [self.supc(self.fx.t, self.fx.b), self.subc(self.fx.t, self.fx.b)],
  46. [(self.fx.b, self.fx.b)],
  47. )
  48. def test_multiple_variables(self) -> None:
  49. self.assert_solve(
  50. [self.fx.t.id, self.fx.s.id],
  51. [
  52. self.supc(self.fx.t, self.fx.b),
  53. self.supc(self.fx.s, self.fx.c),
  54. self.subc(self.fx.t, self.fx.a),
  55. ],
  56. [(self.fx.b, self.fx.a), (self.fx.c, self.fx.o)],
  57. )
  58. def test_no_constraints_for_var(self) -> None:
  59. self.assert_solve([self.fx.t.id], [], [self.fx.uninhabited])
  60. self.assert_solve(
  61. [self.fx.t.id, self.fx.s.id], [], [self.fx.uninhabited, self.fx.uninhabited]
  62. )
  63. self.assert_solve(
  64. [self.fx.t.id, self.fx.s.id],
  65. [self.supc(self.fx.s, self.fx.a)],
  66. [self.fx.uninhabited, (self.fx.a, self.fx.o)],
  67. )
  68. def test_simple_constraints_with_dynamic_type(self) -> None:
  69. self.assert_solve(
  70. [self.fx.t.id], [self.supc(self.fx.t, self.fx.anyt)], [(self.fx.anyt, self.fx.anyt)]
  71. )
  72. self.assert_solve(
  73. [self.fx.t.id],
  74. [self.supc(self.fx.t, self.fx.anyt), self.supc(self.fx.t, self.fx.anyt)],
  75. [(self.fx.anyt, self.fx.anyt)],
  76. )
  77. self.assert_solve(
  78. [self.fx.t.id],
  79. [self.supc(self.fx.t, self.fx.anyt), self.supc(self.fx.t, self.fx.a)],
  80. [(self.fx.anyt, self.fx.anyt)],
  81. )
  82. self.assert_solve(
  83. [self.fx.t.id], [self.subc(self.fx.t, self.fx.anyt)], [(self.fx.anyt, self.fx.anyt)]
  84. )
  85. self.assert_solve(
  86. [self.fx.t.id],
  87. [self.subc(self.fx.t, self.fx.anyt), self.subc(self.fx.t, self.fx.anyt)],
  88. [(self.fx.anyt, self.fx.anyt)],
  89. )
  90. # self.assert_solve([self.fx.t.id],
  91. # [self.subc(self.fx.t, self.fx.anyt),
  92. # self.subc(self.fx.t, self.fx.a)],
  93. # [(self.fx.anyt, self.fx.anyt)])
  94. # TODO: figure out what this should be after changes to meet(any, X)
  95. def test_both_normal_and_any_types_in_results(self) -> None:
  96. # If one of the bounds is any, we promote the other bound to
  97. # any as well, since otherwise the type range does not make sense.
  98. self.assert_solve(
  99. [self.fx.t.id],
  100. [self.supc(self.fx.t, self.fx.a), self.subc(self.fx.t, self.fx.anyt)],
  101. [(self.fx.anyt, self.fx.anyt)],
  102. )
  103. self.assert_solve(
  104. [self.fx.t.id],
  105. [self.supc(self.fx.t, self.fx.anyt), self.subc(self.fx.t, self.fx.a)],
  106. [(self.fx.anyt, self.fx.anyt)],
  107. )
  108. def assert_solve(
  109. self,
  110. vars: list[TypeVarId],
  111. constraints: list[Constraint],
  112. results: list[None | Type | tuple[Type, Type]],
  113. ) -> None:
  114. res: list[Type | None] = []
  115. for r in results:
  116. if isinstance(r, tuple):
  117. res.append(r[0])
  118. else:
  119. res.append(r)
  120. actual = solve_constraints(vars, constraints)
  121. assert_equal(str(actual), str(res))
  122. def supc(self, type_var: TypeVarType, bound: Type) -> Constraint:
  123. return Constraint(type_var, SUPERTYPE_OF, bound)
  124. def subc(self, type_var: TypeVarType, bound: Type) -> Constraint:
  125. return Constraint(type_var, SUBTYPE_OF, bound)