blob: f40996145cba7839afc23479d4929520c2d0ec27 [file] [log] [blame]
from __future__ import annotations
from mypy.constraints import SUBTYPE_OF, SUPERTYPE_OF, Constraint, infer_constraints
from mypy.test.helpers import Suite
from mypy.test.typefixture import TypeFixture
from mypy.types import Instance, TupleType, UnpackType
class ConstraintsSuite(Suite):
def setUp(self) -> None:
self.fx = TypeFixture()
def test_no_type_variables(self) -> None:
assert not infer_constraints(self.fx.o, self.fx.o, SUBTYPE_OF)
def test_basic_type_variable(self) -> None:
fx = self.fx
for direction in [SUBTYPE_OF, SUPERTYPE_OF]:
assert infer_constraints(fx.gt, fx.ga, direction) == [
Constraint(type_var=fx.t, op=direction, target=fx.a)
]
def test_basic_type_var_tuple_subtype(self) -> None:
fx = self.fx
assert infer_constraints(
Instance(fx.gvi, [UnpackType(fx.ts)]), Instance(fx.gvi, [fx.a, fx.b]), SUBTYPE_OF
) == [
Constraint(type_var=fx.ts, op=SUBTYPE_OF, target=TupleType([fx.a, fx.b], fx.std_tuple))
]
def test_basic_type_var_tuple(self) -> None:
fx = self.fx
assert infer_constraints(
Instance(fx.gvi, [UnpackType(fx.ts)]), Instance(fx.gvi, [fx.a, fx.b]), SUPERTYPE_OF
) == [
Constraint(
type_var=fx.ts, op=SUPERTYPE_OF, target=TupleType([fx.a, fx.b], fx.std_tuple)
)
]
def test_type_var_tuple_with_prefix_and_suffix(self) -> None:
fx = self.fx
assert set(
infer_constraints(
Instance(fx.gv2i, [fx.t, UnpackType(fx.ts), fx.s]),
Instance(fx.gv2i, [fx.a, fx.b, fx.c, fx.d]),
SUPERTYPE_OF,
)
) == {
Constraint(type_var=fx.t, op=SUPERTYPE_OF, target=fx.a),
Constraint(
type_var=fx.ts, op=SUPERTYPE_OF, target=TupleType([fx.b, fx.c], fx.std_tuple)
),
Constraint(type_var=fx.s, op=SUPERTYPE_OF, target=fx.d),
}
def test_unpack_homogenous_tuple(self) -> None:
fx = self.fx
assert set(
infer_constraints(
Instance(fx.gvi, [UnpackType(Instance(fx.std_tuplei, [fx.t]))]),
Instance(fx.gvi, [fx.a, fx.b]),
SUPERTYPE_OF,
)
) == {
Constraint(type_var=fx.t, op=SUPERTYPE_OF, target=fx.a),
Constraint(type_var=fx.t, op=SUPERTYPE_OF, target=fx.b),
}
def test_unpack_homogenous_tuple_with_prefix_and_suffix(self) -> None:
fx = self.fx
assert set(
infer_constraints(
Instance(fx.gv2i, [fx.t, UnpackType(Instance(fx.std_tuplei, [fx.s])), fx.u]),
Instance(fx.gv2i, [fx.a, fx.b, fx.c, fx.d]),
SUPERTYPE_OF,
)
) == {
Constraint(type_var=fx.t, op=SUPERTYPE_OF, target=fx.a),
Constraint(type_var=fx.s, op=SUPERTYPE_OF, target=fx.b),
Constraint(type_var=fx.s, op=SUPERTYPE_OF, target=fx.c),
Constraint(type_var=fx.u, op=SUPERTYPE_OF, target=fx.d),
}
def test_unpack_tuple(self) -> None:
fx = self.fx
assert set(
infer_constraints(
Instance(
fx.gvi,
[
UnpackType(
TupleType([fx.t, fx.s], fallback=Instance(fx.std_tuplei, [fx.o]))
)
],
),
Instance(fx.gvi, [fx.a, fx.b]),
SUPERTYPE_OF,
)
) == {
Constraint(type_var=fx.t, op=SUPERTYPE_OF, target=fx.a),
Constraint(type_var=fx.s, op=SUPERTYPE_OF, target=fx.b),
}
def test_unpack_with_prefix_and_suffix(self) -> None:
fx = self.fx
assert set(
infer_constraints(
Instance(
fx.gv2i,
[
fx.u,
UnpackType(
TupleType([fx.t, fx.s], fallback=Instance(fx.std_tuplei, [fx.o]))
),
fx.u,
],
),
Instance(fx.gv2i, [fx.a, fx.b, fx.c, fx.d]),
SUPERTYPE_OF,
)
) == {
Constraint(type_var=fx.u, op=SUPERTYPE_OF, target=fx.a),
Constraint(type_var=fx.t, op=SUPERTYPE_OF, target=fx.b),
Constraint(type_var=fx.s, op=SUPERTYPE_OF, target=fx.c),
Constraint(type_var=fx.u, op=SUPERTYPE_OF, target=fx.d),
}
def test_unpack_tuple_length_non_match(self) -> None:
fx = self.fx
assert set(
infer_constraints(
Instance(
fx.gv2i,
[
fx.u,
UnpackType(
TupleType([fx.t, fx.s], fallback=Instance(fx.std_tuplei, [fx.o]))
),
fx.u,
],
),
Instance(fx.gv2i, [fx.a, fx.b, fx.d]),
SUPERTYPE_OF,
)
# We still get constraints on the prefix/suffix in this case.
) == {
Constraint(type_var=fx.u, op=SUPERTYPE_OF, target=fx.a),
Constraint(type_var=fx.u, op=SUPERTYPE_OF, target=fx.d),
}
def test_var_length_tuple_with_fixed_length_tuple(self) -> None:
fx = self.fx
assert not infer_constraints(
TupleType([fx.t, fx.s], fallback=Instance(fx.std_tuplei, [fx.o])),
Instance(fx.std_tuplei, [fx.a]),
SUPERTYPE_OF,
)