Skip to content

Commit aae2aea

Browse files
committed
Prevent creating types with invalid bounds
1 parent 677289d commit aae2aea

File tree

1 file changed

+25
-13
lines changed

1 file changed

+25
-13
lines changed

src/ir/type_utils.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,11 @@ def _replace_type_argument(base_targ: tp.Type, bound: tp.Type, types,
4949
type_var_map = unify_types(bound, template_t, None)
5050
if not type_var_map:
5151
return None
52-
new_targ, _ = instantiate_type_constructor(
52+
new_targ, type_var_map = instantiate_type_constructor(
5353
base_targ.t_constructor, types, only_regular=True,
54-
type_var_map=type_var_map, variance_choices=None
54+
type_var_map=type_var_map, disable_variance=True
5555
)
56-
type_var_map = new_targ.get_type_variable_assignments()
57-
return base_targ.to_variance_free(type_var_map)
56+
return new_targ.to_variance_free()
5857

5958
# Here, we have a case like the following.
6059
# bound: A<Number, X>
@@ -87,7 +86,8 @@ def _find_candidate_type_args(t_param: tp.TypeParameter,
8786
base_targ: tp.Type,
8887
types,
8988
get_subtypes,
90-
type_var_map={}):
89+
type_var_map={},
90+
ignore_use_variance=False):
9191

9292
bound = None
9393
if t_param.bound:
@@ -118,7 +118,7 @@ def _find_candidate_type_args(t_param: tp.TypeParameter,
118118
base_targ, types,
119119
not get_subtypes, True, bound, concrete_only=True)
120120

121-
if not base_targ.is_wildcard():
121+
if not base_targ.is_wildcard() or ignore_use_variance:
122122
return t_args
123123
if base_targ.is_covariant():
124124
new_types = _find_types(
@@ -137,7 +137,8 @@ def _find_candidate_type_args(t_param: tp.TypeParameter,
137137
return t_args
138138

139139

140-
def _construct_related_types(etype: tp.ParameterizedType, types, get_subtypes):
140+
def _construct_related_types(etype: tp.ParameterizedType, types, get_subtypes,
141+
ignore_use_variance=False):
141142
type_var_map = OrderedDict()
142143
if etype.name == 'Array':
143144
types = [t for t in types
@@ -199,7 +200,8 @@ def _construct_related_types(etype: tp.ParameterizedType, types, get_subtypes):
199200
else:
200201
t_args = _find_candidate_type_args(t_param, etype.type_args[i],
201202
types, get_subtypes,
202-
type_var_map)
203+
type_var_map,
204+
ignore_use_variance)
203205
if not t_args:
204206
# We were not able to construct a subtype of the given
205207
# parameterized type. Therefore, we give back the given
@@ -219,7 +221,7 @@ def to_type(stype, types):
219221

220222

221223
def _find_types(etype, types, get_subtypes, include_self, bound=None,
222-
concrete_only=False):
224+
concrete_only=False, ignore_use_variance=False):
223225

224226
# Otherwise, if we want to find the supertypes of a given type, `bound`
225227
# is interpreted a greatest bound.
@@ -238,7 +240,9 @@ def _find_types(etype, types, get_subtypes, include_self, bound=None,
238240
continue
239241

240242
if isinstance(etype, tp.ParameterizedType):
241-
t_set.add(_construct_related_types(etype, types, get_subtypes))
243+
t_set.add(_construct_related_types(
244+
etype, types, get_subtypes,
245+
ignore_use_variance=ignore_use_variance))
242246
if include_self:
243247
t_set.add(etype)
244248
else:
@@ -250,9 +254,11 @@ def _find_types(etype, types, get_subtypes, include_self, bound=None,
250254

251255

252256
def find_subtypes(etype, types, include_self=False, bound=None,
253-
concrete_only=False):
257+
concrete_only=False,
258+
ignore_use_variance=False):
254259
return _find_types(etype, types, get_subtypes=True,
255-
include_self=include_self, concrete_only=concrete_only)
260+
include_self=include_self, concrete_only=concrete_only,
261+
ignore_use_variance=ignore_use_variance)
256262

257263

258264
def find_supertypes(etype, types, include_self=False, bound=None,
@@ -584,7 +590,13 @@ def _compute_type_variable_assignments(
584590
bound = t_param.bound
585591
# If the type parameter has a bound, then find types
586592
# that are subtypes to this bound.
587-
a_types = find_subtypes(bound, types, True)
593+
# Note that at this point we ignore use variance
594+
# to prevent creating invalid types, e.g.,
595+
# * bound: Foo<X, X>
596+
# * X is assigned to out Number
597+
# * Prevent creating Foo<Long, Number>
598+
a_types = find_subtypes(bound, types, True,
599+
ignore_use_variance=True)
588600
for i, t in enumerate(a_types):
589601
if isinstance(t, tp.ParameterizedType):
590602
a_types[i] = t.to_variance_free()

0 commit comments

Comments
 (0)