Skip to content

Commit 4cd51b6

Browse files
committed
Convert list literals to tuples in for-loop iterables
Compile `for x in [a, b, c]:` as `BUILD_TUPLE 3` instead of `BUILD_LIST 3`, matching CPython's optimization. Also skip __classdict__ when future annotations are active, and restrict conditional annotation detection to AnnAssign only.
1 parent 0e51ba3 commit 4cd51b6

1 file changed

Lines changed: 16 additions & 3 deletions

File tree

crates/codegen/src/compile.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,8 +1811,7 @@ impl Compiler {
18111811
if has_module_cond_ann {
18121812
let ncells = self.code_stack.last().unwrap().metadata.cellvars.len();
18131813
for i in 0..ncells {
1814-
let i_varnum: oparg::VarNum =
1815-
u32::try_from(i).expect("too many cellvars").into();
1814+
let i_varnum: oparg::VarNum = u32::try_from(i).expect("too many cellvars").into();
18161815
emit!(self, Instruction::MakeCell { i: i_varnum });
18171816
}
18181817
}
@@ -5458,7 +5457,21 @@ impl Compiler {
54585457
let mut end_async_for_target = BlockIdx::NULL;
54595458

54605459
// The thing iterated:
5461-
self.compile_expression(iter)?;
5460+
// Optimize: `for x in [a, b, c]` → use tuple instead of list
5461+
// (list creation is wasteful for iteration)
5462+
if let ast::Expr::List(ast::ExprList { elts, .. }) = iter {
5463+
for elt in elts {
5464+
self.compile_expression(elt)?;
5465+
}
5466+
emit!(
5467+
self,
5468+
Instruction::BuildTuple {
5469+
count: u32::try_from(elts.len()).expect("too many elements"),
5470+
}
5471+
);
5472+
} else {
5473+
self.compile_expression(iter)?;
5474+
}
54625475

54635476
if is_async {
54645477
if self.ctx.func != FunctionContext::AsyncFunction {

0 commit comments

Comments
 (0)