Skip to content

Commit 26e58f9

Browse files
committed
Fix type unification for type params and combound types
1 parent 137b474 commit 26e58f9

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

src/ir/type_utils.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,8 +1042,12 @@ class B : A<String>()
10421042
"""
10431043
if t2.is_combound() and not t2.is_parameterized():
10441044
return t2.unify_types(t1, factory, same_type)
1045-
elif t1.is_combound() and not t1.is_parameterized() and t2.is_type_var():
1046-
return {t2: t1}
1045+
elif t1.is_combound() and t2.is_type_var():
1046+
bound = t2.get_bound_rec(factory)
1047+
if bound is None or t1.is_subtype(bound):
1048+
return {t2: t1}
1049+
else:
1050+
return {}
10471051

10481052
if same_type and type(t1) != type(t2):
10491053
return {}

tests/test_typescript.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import src.ir.types as tp
55
import src.ir.type_utils as tu
66

7+
78
def test_type_alias_with_literals():
89
string_alias = ts_ast.TypeAliasDeclaration("Foo", tst.StringType()).get_type()
910
number_alias = ts_ast.TypeAliasDeclaration("Bar", tst.NumberType()).get_type()
@@ -16,6 +17,7 @@ def test_type_alias_with_literals():
1617
assert number_lit.is_subtype(number_alias)
1718
assert not number_alias.is_subtype(number_lit)
1819

20+
1921
def test_type_alias_with_literals2():
2022
string_alias = ts_ast.TypeAliasDeclaration("Foo", tst.StringLiteralType("foo")).get_type()
2123
number_alias = ts_ast.TypeAliasDeclaration("Bar", tst.NumberLiteralType(5)).get_type()
@@ -28,6 +30,7 @@ def test_type_alias_with_literals2():
2830
assert string_alias.is_subtype(string_lit)
2931
assert number_alias.is_subtype(number_lit)
3032

33+
3134
def test_union_types_simple():
3235
union_1 = tst.UnionType([tst.NumberType(), tst.BooleanType()])
3336

@@ -42,6 +45,11 @@ def test_union_types_simple():
4245
assert union_1.is_subtype(union_3)
4346

4447

48+
def test_union_types_other_types():
49+
union = tst.UnionType([tst.NumberType(), tst.BooleanType()])
50+
assert tst.NumberType().is_subtype(union)
51+
52+
4553
def test_union_type_assign():
4654
union = tst.UnionType([tst.StringType(), tst.NumberType(), tst.BooleanType(), tst.ObjectType()])
4755
foo = tst.StringType()
@@ -130,6 +138,22 @@ def test_union_type_unification_type_var():
130138
assert len(type_var_map) == 1
131139
assert type_var_map == {type_param: union}
132140

141+
# Case 2: unify a union with a bounded type param, which has an
142+
# incompatible bound with the given union.
143+
union = tst.UnionType([tst.NumberType(), tst.StringType()])
144+
type_param = tp.TypeParameter("T", bound=tst.NumberType())
145+
146+
type_var_map = tu.unify_types(union, type_param,
147+
tst.TypeScriptBuiltinFactory())
148+
assert type_var_map == {}
149+
150+
151+
# Case 3: unify a union with a bounded type param, which has a compatible
152+
# bound with the given union.
153+
type_param = tp.TypeParameter("T", bound=union)
154+
type_var_map = tu.unify_types(union, type_param,
155+
tst.TypeScriptBuiltinFactory())
156+
assert type_var_map == {type_param: union}
133157

134158
def test_union_type_unification():
135159
type_param = tp.TypeParameter("T")
@@ -149,6 +173,7 @@ def test_union_type_unification():
149173
assert type_param, type_param2 in type_var_map
150174
assert union1.types[1], union1.types[2] in type_var_map.values()
151175

176+
152177
def test_union_type_unification2():
153178
union = tst.UnionType([tst.NumberType(), tst.StringType()])
154179
assert tu.unify_types(tst.BooleanType(), union, tst.TypeScriptBuiltinFactory()) == {}

0 commit comments

Comments
 (0)