Skip to content

Commit d464119

Browse files
committed
vm: restore FOR_ITER_GEN specialization and tuple index parity
1 parent 42d81ff commit d464119

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

crates/vm/src/builtins/tuple.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,13 @@ impl PyTuple {
327327

328328
fn _getitem(&self, needle: &PyObject, vm: &VirtualMachine) -> PyResult {
329329
match SequenceIndex::try_from_borrowed_object(vm, needle, "tuple")? {
330-
SequenceIndex::Int(i) => self.elements.getitem_by_index(vm, i),
330+
SequenceIndex::Int(i) => {
331+
let index = self
332+
.elements
333+
.wrap_index(i)
334+
.ok_or_else(|| vm.new_index_error("tuple index out of range"))?;
335+
Ok(self.elements[index].clone())
336+
}
331337
SequenceIndex::Slice(slice) => self
332338
.elements
333339
.getitem_by_slice(vm, slice)

crates/vm/src/frame.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4612,12 +4612,27 @@ impl ExecutingFrame<'_> {
46124612
}
46134613
}
46144614
Instruction::ForIterGen => {
4615-
// ForIterGen is not faithfully implementable without inline
4616-
// generator frame resumption (as CPython does). Fall through
4617-
// to the generic path so the debugger sees StopIteration.
46184615
let target = bytecode::Label(self.lasti() + 1 + u32::from(arg));
4619-
self.execute_for_iter(vm, target)?;
4620-
Ok(None)
4616+
let iter = self.top_value();
4617+
if let Some(generator) = iter.downcast_ref_if_exact::<PyGenerator>(vm) {
4618+
match generator.as_coro().send(iter, vm.ctx.none(), vm) {
4619+
Ok(PyIterReturn::Return(value)) => {
4620+
self.push_value(value);
4621+
}
4622+
Ok(PyIterReturn::StopIteration(value)) => {
4623+
if vm.use_tracing.get() && !vm.is_none(&self.object.trace.lock()) {
4624+
let stop_exc = vm.new_stop_iteration(value);
4625+
self.fire_exception_trace(&stop_exc, vm)?;
4626+
}
4627+
self.for_iter_jump_on_exhausted(target);
4628+
}
4629+
Err(e) => return Err(e),
4630+
}
4631+
Ok(None)
4632+
} else {
4633+
self.execute_for_iter(vm, target)?;
4634+
Ok(None)
4635+
}
46214636
}
46224637
Instruction::LoadGlobalModule => {
46234638
let oparg = u32::from(arg);
@@ -7299,6 +7314,8 @@ impl ExecutingFrame<'_> {
72997314
Some(Instruction::ForIterList)
73007315
} else if iter.downcast_ref_if_exact::<PyTupleIterator>(vm).is_some() {
73017316
Some(Instruction::ForIterTuple)
7317+
} else if iter.downcast_ref_if_exact::<PyGenerator>(vm).is_some() {
7318+
Some(Instruction::ForIterGen)
73027319
} else {
73037320
None
73047321
};

0 commit comments

Comments
 (0)