Skip to content
4 changes: 3 additions & 1 deletion mypyc/irbuild/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -990,8 +990,10 @@ def get_sequence_type_from_type(self, target_type: Type) -> RType:
elif isinstance(target_type, TypeVarLikeType):
return self.get_sequence_type_from_type(target_type.upper_bound)
elif isinstance(target_type, TupleType):
items = target_type.items
assert items, "This function does not support empty tuples"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary but would have been marginally helpful

# Tuple might have elements of different types.
rtypes = {self.mapper.type_to_rtype(item) for item in target_type.items}
rtypes = set(map(self.mapper.type_to_rtype, items))
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this looks more readable than the brackets when you're scanning quickly

if len(rtypes) == 1:
return rtypes.pop()
else:
Expand Down
36 changes: 26 additions & 10 deletions mypyc/irbuild/for_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,24 +242,40 @@ def sequence_from_generator_preallocate_helper(
rtype = builder.node_type(sequence_expr)
if not (is_sequence_rprimitive(rtype) or isinstance(rtype, RTuple)):
return None
sequence = builder.accept(sequence_expr)
length = get_expr_length_value(builder, sequence_expr, sequence, line, use_pyssize_t=True)

if isinstance(rtype, RTuple):
# If input is RTuple, box it to tuple_rprimitive for generic iteration
# TODO: this can be optimized a bit better with an unrolled ForRTuple helper
proper_type = get_proper_type(builder.types[sequence_expr])
assert isinstance(proper_type, TupleType), proper_type

# the for_loop_helper_with_index crashes for empty tuples, bail out
if not proper_type.items:
return None

proper_types = get_proper_types(proper_type.items)

if all(isinstance(typ, LiteralType) for typ in proper_types):
get_item_ops = [LoadLiteral(typ.value, object_rprimitive) for typ in proper_types]

get_item_ops = [
(
LoadLiteral(typ.value, object_rprimitive)
if isinstance(typ, LiteralType)
else TupleGet(sequence, i, line)
)
for i, typ in enumerate(get_proper_types(proper_type.items))
]
else:
sequence = builder.accept(sequence_expr)
get_item_ops = [
(
LoadLiteral(typ.value, object_rprimitive)
if isinstance(typ, LiteralType)
else TupleGet(sequence, i, line)
)
for i, typ in enumerate(proper_types)
]

items = list(map(builder.add, get_item_ops))
sequence = builder.new_tuple(items, line)

else:
sequence = builder.accept(sequence_expr)

length = get_expr_length_value(builder, sequence_expr, sequence, line, use_pyssize_t=True)

target_op = empty_op_llbuilder(length, line)

Expand Down
Loading