refactor(checker): extract reduce_types function
This commit is contained in:
@@ -502,34 +502,17 @@ class PythonTyper(
|
||||
def visit_list_expr(self, expr: p.ListExpr) -> Type:
|
||||
list_type: Type = self.types.get_type("list")
|
||||
item_types: list[Type] = [self.type_of(item) for item in expr.items]
|
||||
item_types = self.types.reduce_types(item_types)
|
||||
|
||||
# Try to reduce types with subsumption
|
||||
reduced: bool = True
|
||||
keep: list[int] = list(range(len(item_types)))
|
||||
while reduced:
|
||||
reduced = False
|
||||
for i, i1 in enumerate(keep):
|
||||
type1: Type = item_types[i1]
|
||||
for i2 in keep[i + 1 :]:
|
||||
type2 = item_types[i2]
|
||||
if self.types.is_subtype(type1, type2):
|
||||
keep.remove(i1)
|
||||
elif self.types.is_subtype(type2, type1):
|
||||
keep.remove(i2)
|
||||
else:
|
||||
continue
|
||||
reduced = True
|
||||
break
|
||||
|
||||
if len(keep) == 0:
|
||||
if len(item_types) == 0:
|
||||
return list_type
|
||||
|
||||
if len(keep) == 1:
|
||||
item_type: Type = item_types[keep[0]]
|
||||
if len(item_types) == 1:
|
||||
item_type: Type = item_types[0]
|
||||
return self.types.apply_generic(list_type, [item_type])
|
||||
self.reporter.error(
|
||||
expr.location,
|
||||
f"Heterogeneous list items: {[item_types[i] for i in keep]}",
|
||||
f"Heterogeneous list items: {item_types}",
|
||||
)
|
||||
return self.types.apply_generic(list_type, [UnknownType()])
|
||||
|
||||
|
||||
@@ -283,3 +283,31 @@ class TypesRegistry:
|
||||
|
||||
case _:
|
||||
raise ValueError(f"{type} is not a generic type")
|
||||
|
||||
def reduce_types(self, types: list[Type]) -> list[Type]:
|
||||
"""Reduce a list of types to remove subtypes and only keep the highest types
|
||||
|
||||
Args:
|
||||
types (list[Type]): the types to reduce
|
||||
|
||||
Returns:
|
||||
list[Type]: the reduced list of types
|
||||
"""
|
||||
|
||||
reduced: bool = True
|
||||
keep: list[int] = list(range(len(types)))
|
||||
while reduced:
|
||||
reduced = False
|
||||
for i, i1 in enumerate(keep):
|
||||
type1: Type = types[i1]
|
||||
for i2 in keep[i + 1 :]:
|
||||
type2 = types[i2]
|
||||
if self.is_subtype(type1, type2):
|
||||
keep.remove(i1)
|
||||
elif self.is_subtype(type2, type1):
|
||||
keep.remove(i2)
|
||||
else:
|
||||
continue
|
||||
reduced = True
|
||||
break
|
||||
return [types[i] for i in keep]
|
||||
|
||||
Reference in New Issue
Block a user