diff --git a/vm/src/builtins/asyncgenerator.rs b/vm/src/builtins/asyncgenerator.rs index 10e1b0477c..57c256e12a 100644 --- a/vm/src/builtins/asyncgenerator.rs +++ b/vm/src/builtins/asyncgenerator.rs @@ -5,7 +5,7 @@ use crate::coroutine::{Coro, Variant}; use crate::exceptions::PyBaseExceptionRef; use crate::frame::FrameRef; use crate::function::OptionalArg; -use crate::slots::PyIter; +use crate::slots::{IteratorIterable, PyIter}; use crate::vm::VirtualMachine; use crate::{ IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, @@ -256,6 +256,7 @@ impl PyAsyncGenASend { } } +impl IteratorIterable for PyAsyncGenASend {} impl PyIter for PyAsyncGenASend { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { zelf.send(vm.ctx.none(), vm) @@ -397,6 +398,7 @@ impl PyAsyncGenAThrow { } } +impl IteratorIterable for PyAsyncGenAThrow {} impl PyIter for PyAsyncGenAThrow { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { zelf.send(vm.ctx.none(), vm) diff --git a/vm/src/builtins/bytearray.rs b/vm/src/builtins/bytearray.rs index 24c7e2bfb4..20075aa6de 100644 --- a/vm/src/builtins/bytearray.rs +++ b/vm/src/builtins/bytearray.rs @@ -21,7 +21,8 @@ use crate::common::lock::{ use crate::function::{ArgIterable, FuncArgs, OptionalArg, OptionalOption}; use crate::sliceable::{PySliceableSequence, PySliceableSequenceMut, SequenceIndex}; use crate::slots::{ - AsBuffer, Callable, Comparable, Hashable, Iterable, PyComparisonOp, PyIter, Unhashable, + AsBuffer, Callable, Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, PyIter, + Unhashable, }; use crate::utils::Either; use crate::vm::VirtualMachine; @@ -747,6 +748,7 @@ impl PyValue for PyByteArrayIterator { #[pyimpl(with(PyIter))] impl PyByteArrayIterator {} +impl IteratorIterable for PyByteArrayIterator {} impl PyIter for PyByteArrayIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let pos = zelf.position.fetch_add(1); diff --git a/vm/src/builtins/bytes.rs b/vm/src/builtins/bytes.rs index 61af29c2d1..6e7c9ec2c0 100644 --- a/vm/src/builtins/bytes.rs +++ b/vm/src/builtins/bytes.rs @@ -13,7 +13,8 @@ use crate::byteslike::ArgBytesLike; use crate::common::hash::PyHash; use crate::function::{ArgIterable, OptionalArg, OptionalOption}; use crate::slots::{ - AsBuffer, Callable, Comparable, Hashable, Iterable, PyComparisonOp, PyIter, SlotConstructor, + AsBuffer, Callable, Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, PyIter, + SlotConstructor, }; use crate::utils::Either; use crate::vm::VirtualMachine; @@ -601,6 +602,7 @@ impl PyValue for PyBytesIterator { #[pyimpl(with(PyIter))] impl PyBytesIterator {} +impl IteratorIterable for PyBytesIterator {} impl PyIter for PyBytesIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let pos = zelf.position.fetch_add(1); diff --git a/vm/src/builtins/coroutine.rs b/vm/src/builtins/coroutine.rs index 75e9cea181..9cd9574906 100644 --- a/vm/src/builtins/coroutine.rs +++ b/vm/src/builtins/coroutine.rs @@ -4,7 +4,7 @@ use super::pytype::PyTypeRef; use crate::coroutine::{Coro, Variant}; use crate::frame::FrameRef; use crate::function::OptionalArg; -use crate::slots::PyIter; +use crate::slots::{IteratorIterable, PyIter}; use crate::vm::VirtualMachine; use crate::{IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; @@ -104,6 +104,7 @@ impl PyCoroutine { } } +impl IteratorIterable for PyCoroutine {} impl PyIter for PyCoroutine { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { zelf.send(vm.ctx.none(), vm) @@ -141,6 +142,7 @@ impl PyCoroutineWrapper { } } +impl IteratorIterable for PyCoroutineWrapper {} impl PyIter for PyCoroutineWrapper { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { zelf.send(vm.ctx.none(), vm) diff --git a/vm/src/builtins/dict.rs b/vm/src/builtins/dict.rs index d8f38700a0..3d04840e62 100644 --- a/vm/src/builtins/dict.rs +++ b/vm/src/builtins/dict.rs @@ -10,7 +10,9 @@ use crate::dictdatatype::{self, DictKey}; use crate::exceptions::PyBaseExceptionRef; use crate::function::{ArgIterable, FuncArgs, KwArgs, OptionalArg}; use crate::iterator; -use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter, Unhashable}; +use crate::slots::{ + Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, PyIter, Unhashable, +}; use crate::vm::{ReprGuard, VirtualMachine}; use crate::{ IdProtocol, IntoPyObject, ItemProtocol, PyArithmaticValue::*, PyAttributes, PyClassDef, @@ -731,6 +733,7 @@ macro_rules! dict_iterator { } } + impl IteratorIterable for $iter_name {} impl PyIter for $iter_name { #[allow(clippy::redundant_closure_call)] fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { @@ -791,6 +794,7 @@ macro_rules! dict_iterator { } } + impl IteratorIterable for $reverse_iter_name {} impl PyIter for $reverse_iter_name { #[allow(clippy::redundant_closure_call)] fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { diff --git a/vm/src/builtins/enumerate.rs b/vm/src/builtins/enumerate.rs index 302a250828..a3735c6e38 100644 --- a/vm/src/builtins/enumerate.rs +++ b/vm/src/builtins/enumerate.rs @@ -11,7 +11,7 @@ use super::iter::{ }; use super::pytype::PyTypeRef; use crate::function::OptionalArg; -use crate::slots::{PyIter, SlotConstructor}; +use crate::slots::{IteratorIterable, PyIter, SlotConstructor}; use crate::vm::VirtualMachine; use crate::{iterator, ItemProtocol, TypeProtocol}; use crate::{IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; @@ -56,6 +56,7 @@ impl SlotConstructor for PyEnumerate { #[pyimpl(with(PyIter, SlotConstructor), flags(BASETYPE))] impl PyEnumerate {} +impl IteratorIterable for PyEnumerate {} impl PyIter for PyEnumerate { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let next_obj = iterator::call_next(vm, &zelf.iterator)?; @@ -137,6 +138,7 @@ impl PyReverseSequenceIterator { } } +impl IteratorIterable for PyReverseSequenceIterator {} impl PyIter for PyReverseSequenceIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { if let Exhausted = zelf.status.load() { diff --git a/vm/src/builtins/filter.rs b/vm/src/builtins/filter.rs index 251fa0c81c..c06726fbe1 100644 --- a/vm/src/builtins/filter.rs +++ b/vm/src/builtins/filter.rs @@ -1,6 +1,6 @@ use super::pytype::PyTypeRef; use crate::iterator; -use crate::slots::{PyIter, SlotConstructor}; +use crate::slots::{IteratorIterable, PyIter, SlotConstructor}; use crate::vm::VirtualMachine; use crate::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; @@ -50,6 +50,7 @@ impl SlotConstructor for PyFilter { #[pyimpl(with(PyIter, SlotConstructor), flags(BASETYPE))] impl PyFilter {} +impl IteratorIterable for PyFilter {} impl PyIter for PyFilter { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let predicate = &zelf.predicate; diff --git a/vm/src/builtins/generator.rs b/vm/src/builtins/generator.rs index 125ac9a590..e7bf156fc1 100644 --- a/vm/src/builtins/generator.rs +++ b/vm/src/builtins/generator.rs @@ -8,7 +8,7 @@ use super::pytype::PyTypeRef; use crate::coroutine::{Coro, Variant}; use crate::frame::FrameRef; use crate::function::OptionalArg; -use crate::slots::PyIter; +use crate::slots::{IteratorIterable, PyIter}; use crate::vm::VirtualMachine; use crate::{IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; @@ -95,6 +95,7 @@ impl PyGenerator { } } +impl IteratorIterable for PyGenerator {} impl PyIter for PyGenerator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { zelf.send(vm.ctx.none(), vm) diff --git a/vm/src/builtins/iter.rs b/vm/src/builtins/iter.rs index 95f2f53afa..af047326b9 100644 --- a/vm/src/builtins/iter.rs +++ b/vm/src/builtins/iter.rs @@ -6,7 +6,7 @@ use crossbeam_utils::atomic::AtomicCell; use super::pytype::PyTypeRef; use super::{int, PyInt}; -use crate::slots::PyIter; +use crate::slots::{IteratorIterable, PyIter}; use crate::vm::VirtualMachine; use crate::{ function::ArgCallable, ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, @@ -92,6 +92,7 @@ impl PySequenceIterator { } } +impl IteratorIterable for PySequenceIterator {} impl PyIter for PySequenceIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { if let IterStatus::Exhausted = zelf.status.load() { @@ -134,6 +135,7 @@ impl PyCallableIterator { } } +impl IteratorIterable for PyCallableIterator {} impl PyIter for PyCallableIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { if let IterStatus::Exhausted = zelf.status.load() { diff --git a/vm/src/builtins/list.rs b/vm/src/builtins/list.rs index 9e7ae2adb6..e0200f12af 100644 --- a/vm/src/builtins/list.rs +++ b/vm/src/builtins/list.rs @@ -20,7 +20,9 @@ use crate::common::lock::{ use crate::function::{ArgIterable, FuncArgs, OptionalArg}; use crate::sequence::{self, SimpleSeq}; use crate::sliceable::{PySliceableSequence, PySliceableSequenceMut, SequenceIndex}; -use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter, Unhashable}; +use crate::slots::{ + Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, PyIter, Unhashable, +}; use crate::utils::Either; use crate::vm::{ReprGuard, VirtualMachine}; use crate::{ @@ -526,6 +528,7 @@ impl PyListIterator { } } +impl IteratorIterable for PyListIterator {} impl PyIter for PyListIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { if let Exhausted = zelf.status.load() { @@ -599,6 +602,7 @@ impl PyListReverseIterator { } } +impl IteratorIterable for PyListReverseIterator {} impl PyIter for PyListReverseIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { if let Exhausted = zelf.status.load() { diff --git a/vm/src/builtins/map.rs b/vm/src/builtins/map.rs index c530f0fe5b..fbf72d3878 100644 --- a/vm/src/builtins/map.rs +++ b/vm/src/builtins/map.rs @@ -1,7 +1,7 @@ use super::pytype::PyTypeRef; use crate::function::PosArgs; use crate::iterator; -use crate::slots::{PyIter, SlotConstructor}; +use crate::slots::{IteratorIterable, PyIter, SlotConstructor}; use crate::vm::VirtualMachine; use crate::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; @@ -50,6 +50,7 @@ impl PyMap { } } +impl IteratorIterable for PyMap {} impl PyIter for PyMap { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let next_objs = zelf diff --git a/vm/src/builtins/pystr.rs b/vm/src/builtins/pystr.rs index f877caef8f..7f07fb2510 100644 --- a/vm/src/builtins/pystr.rs +++ b/vm/src/builtins/pystr.rs @@ -11,7 +11,9 @@ use crate::exceptions::IntoPyException; use crate::format::{FormatSpec, FormatString, FromTemplate}; use crate::function::{ArgIterable, FuncArgs, OptionalArg, OptionalOption}; use crate::sliceable::PySliceableSequence; -use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter, SlotConstructor}; +use crate::slots::{ + Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, PyIter, SlotConstructor, +}; use crate::utils::Either; use crate::VirtualMachine; use crate::{ @@ -227,6 +229,7 @@ impl PyStrIterator { } } +impl IteratorIterable for PyStrIterator {} impl PyIter for PyStrIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { if let Exhausted = zelf.status.load() { diff --git a/vm/src/builtins/range.rs b/vm/src/builtins/range.rs index 3543a0e0f0..c69300979f 100644 --- a/vm/src/builtins/range.rs +++ b/vm/src/builtins/range.rs @@ -9,7 +9,7 @@ use super::pytype::PyTypeRef; use super::slice::{PySlice, PySliceRef}; use crate::common::hash::PyHash; use crate::function::{FuncArgs, OptionalArg}; -use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter}; +use crate::slots::{Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, PyIter}; use crate::vm::VirtualMachine; use crate::{ iterator, IdProtocol, IntoPyRef, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, @@ -516,6 +516,7 @@ impl PyLongRangeIterator { } } +impl IteratorIterable for PyLongRangeIterator {} impl PyIter for PyLongRangeIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { // TODO: In pathological case (index == usize::MAX) this can wrap around @@ -585,6 +586,7 @@ impl PyRangeIterator { } } +impl IteratorIterable for PyRangeIterator {} impl PyIter for PyRangeIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { // TODO: In pathological case (index == usize::MAX) this can wrap around diff --git a/vm/src/builtins/set.rs b/vm/src/builtins/set.rs index eef2f9e3e9..a94c8b9e18 100644 --- a/vm/src/builtins/set.rs +++ b/vm/src/builtins/set.rs @@ -8,7 +8,8 @@ use crate::dictdatatype; use crate::dictdatatype::DictSize; use crate::function::{ArgIterable, FuncArgs, OptionalArg, PosArgs}; use crate::slots::{ - Comparable, Hashable, Iterable, PyComparisonOp, PyIter, SlotConstructor, Unhashable, + Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, PyIter, SlotConstructor, + Unhashable, }; use crate::vm::{ReprGuard, VirtualMachine}; use crate::{ @@ -864,6 +865,7 @@ impl PySetIterator { } } +impl IteratorIterable for PySetIterator {} impl PyIter for PySetIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { match zelf.status.load() { diff --git a/vm/src/builtins/tuple.rs b/vm/src/builtins/tuple.rs index 9e29a63b5e..b935d313cd 100644 --- a/vm/src/builtins/tuple.rs +++ b/vm/src/builtins/tuple.rs @@ -15,7 +15,9 @@ use crate::common::hash::PyHash; use crate::function::OptionalArg; use crate::sequence::{self, SimpleSeq}; use crate::sliceable::PySliceableSequence; -use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter, SlotConstructor}; +use crate::slots::{ + Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, PyIter, SlotConstructor, +}; use crate::utils::Either; use crate::vm::{ReprGuard, VirtualMachine}; use crate::{ @@ -378,6 +380,7 @@ impl PyTupleIterator { } } +impl IteratorIterable for PyTupleIterator {} impl PyIter for PyTupleIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { if let Exhausted = zelf.status.load() { diff --git a/vm/src/builtins/zip.rs b/vm/src/builtins/zip.rs index bd3c76c9cb..19074779fa 100644 --- a/vm/src/builtins/zip.rs +++ b/vm/src/builtins/zip.rs @@ -1,7 +1,7 @@ use super::pytype::PyTypeRef; use crate::function::PosArgs; use crate::iterator; -use crate::slots::{PyIter, SlotConstructor}; +use crate::slots::{IteratorIterable, PyIter, SlotConstructor}; use crate::vm::VirtualMachine; use crate::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; @@ -32,6 +32,7 @@ impl SlotConstructor for PyZip { #[pyimpl(with(PyIter, SlotConstructor), flags(BASETYPE))] impl PyZip {} +impl IteratorIterable for PyZip {} impl PyIter for PyZip { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { if zelf.iterators.is_empty() { diff --git a/vm/src/slots.rs b/vm/src/slots.rs index 93d2ea735a..571713db2b 100644 --- a/vm/src/slots.rs +++ b/vm/src/slots.rs @@ -533,6 +533,7 @@ pub trait AsBuffer: PyValue { #[pyimpl] pub trait Iterable: PyValue { #[pyslot] + #[pymethod(name = "__iter__")] fn tp_iter(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult { if let Ok(zelf) = zelf.downcast() { Self::iter(zelf, vm) @@ -541,12 +542,11 @@ pub trait Iterable: PyValue { } } - #[pymethod(magic)] fn iter(zelf: PyRef, vm: &VirtualMachine) -> PyResult; } #[pyimpl(with(Iterable))] -pub trait PyIter: PyValue { +pub trait PyIter: PyValue + Iterable { #[pyslot] fn tp_iternext(zelf: &PyObjectRef, vm: &VirtualMachine) -> PyResult { if let Some(zelf) = zelf.downcast_ref() { @@ -559,19 +559,21 @@ pub trait PyIter: PyValue { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult; #[pymethod] - fn __next__(zelf: PyRef, vm: &VirtualMachine) -> PyResult { - Self::next(&zelf, vm) + fn __next__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult { + Self::tp_iternext(&zelf, vm) } } +pub trait IteratorIterable: PyValue {} + impl Iterable for T where - T: PyIter, + T: IteratorIterable, { fn tp_iter(zelf: PyObjectRef, _vm: &VirtualMachine) -> PyResult { Ok(zelf) } - fn iter(zelf: PyRef, _vm: &VirtualMachine) -> PyResult { - Ok(zelf.into_object()) + fn iter(_zelf: PyRef, _vm: &VirtualMachine) -> PyResult { + unreachable!("tp_iter is implemented"); } } diff --git a/vm/src/stdlib/array.rs b/vm/src/stdlib/array.rs index 30b9f958b8..da67abd16b 100644 --- a/vm/src/stdlib/array.rs +++ b/vm/src/stdlib/array.rs @@ -19,7 +19,10 @@ mod array { byteslike::ArgBytesLike, function::{ArgIterable, OptionalArg}, sliceable::{saturate_index, PySliceableSequence, PySliceableSequenceMut, SequenceIndex}, - slots::{AsBuffer, Comparable, Iterable, PyComparisonOp, PyIter, SlotConstructor}, + slots::{ + AsBuffer, Comparable, Iterable, IteratorIterable, PyComparisonOp, PyIter, + SlotConstructor, + }, IdProtocol, IntoPyObject, IntoPyResult, PyComparisonValue, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, VirtualMachine, }; @@ -1191,6 +1194,7 @@ mod array { #[pyimpl(with(PyIter))] impl PyArrayIter {} + impl IteratorIterable for PyArrayIter {} impl PyIter for PyArrayIter { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let pos = zelf.position.fetch_add(1); diff --git a/vm/src/stdlib/collections.rs b/vm/src/stdlib/collections.rs index 640eb24a6b..d675fcff6c 100644 --- a/vm/src/stdlib/collections.rs +++ b/vm/src/stdlib/collections.rs @@ -11,7 +11,8 @@ mod _collections { function::{FuncArgs, KwArgs, OptionalArg}, sequence, sliceable, slots::{ - Comparable, Hashable, Iterable, PyComparisonOp, PyIter, SlotConstructor, Unhashable, + Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, PyIter, + SlotConstructor, Unhashable, }, vm::ReprGuard, PyComparisonValue, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, VirtualMachine, @@ -639,6 +640,7 @@ mod _collections { } } + impl IteratorIterable for PyDequeIterator {} impl PyIter for PyDequeIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { match zelf.status.load() { @@ -718,6 +720,7 @@ mod _collections { } } + impl IteratorIterable for PyReverseDequeIterator {} impl PyIter for PyReverseDequeIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { match zelf.status.load() { diff --git a/vm/src/stdlib/csv.rs b/vm/src/stdlib/csv.rs index 33843fb3c0..0eb8ad170e 100644 --- a/vm/src/stdlib/csv.rs +++ b/vm/src/stdlib/csv.rs @@ -3,7 +3,7 @@ use crate::{ builtins::{PyStr, PyStrRef}, function::{ArgIterable, ArgumentError, FromArgs, FuncArgs}, iterator, - slots::PyIter, + slots::{IteratorIterable, PyIter}, types::create_simple_type, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, VirtualMachine, @@ -97,6 +97,7 @@ impl fmt::Debug for Reader { #[pyimpl(with(PyIter))] impl Reader {} +impl IteratorIterable for Reader {} impl PyIter for Reader { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let string = iterator::call_next(vm, &zelf.iter)?; diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 0f9567faf3..a5ac4f5db7 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -89,7 +89,7 @@ mod _io { use crate::common::rc::PyRc; use crate::exceptions::{self, PyBaseExceptionRef}; use crate::function::{ArgIterable, FuncArgs, OptionalArg, OptionalOption}; - use crate::slots::SlotConstructor; + use crate::slots::{Iterable, PyIter, SlotConstructor}; use crate::utils::Either; use crate::vm::{ReprGuard, VirtualMachine}; use crate::{ @@ -340,9 +340,10 @@ mod _io { #[pyattr] #[pyclass(name = "_IOBase")] + #[derive(Debug, PyValue)] struct _IOBase; - #[pyimpl(flags(BASETYPE, HAS_DICT))] + #[pyimpl(with(PyIter), flags(BASETYPE, HAS_DICT))] impl _IOBase { #[pymethod] fn seek( @@ -508,25 +509,31 @@ mod _io { fn check_seekable(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { check_seekable(&instance, vm) } + } - #[pyslot] - #[pymethod(name = "__iter__")] - fn tp_iter(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult { - check_closed(&instance, vm)?; - Ok(instance) + impl Iterable for _IOBase { + fn tp_iter(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult { + check_closed(&zelf, vm)?; + Ok(zelf) } - #[pyslot] - fn tp_iternext(instance: &PyObjectRef, vm: &VirtualMachine) -> PyResult { - let line = vm.call_method(instance, "readline", ())?; + + fn iter(_zelf: PyRef, _vm: &VirtualMachine) -> PyResult { + unreachable!("tp_iter is implemented") + } + } + + impl PyIter for _IOBase { + fn tp_iternext(zelf: &PyObjectRef, vm: &VirtualMachine) -> PyResult { + let line = vm.call_method(zelf, "readline", ())?; if !line.clone().try_to_bool(vm)? { Err(vm.new_stop_iteration()) } else { Ok(line) } } - #[pymethod(magic)] - fn next(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult { - Self::tp_iternext(&instance, vm) + + fn next(_zelf: &PyRef, _vm: &VirtualMachine) -> PyResult { + unreachable!("tp_iternext is implemented") } } diff --git a/vm/src/stdlib/itertools.rs b/vm/src/stdlib/itertools.rs index 83de9a59e4..ce580d7178 100644 --- a/vm/src/stdlib/itertools.rs +++ b/vm/src/stdlib/itertools.rs @@ -10,7 +10,7 @@ mod decl { builtins::{int, PyInt, PyIntRef, PyTupleRef, PyTypeRef}, function::{ArgCallable, FuncArgs, OptionalArg, OptionalOption, PosArgs}, iterator::{call_next, get_iter, get_next_object}, - slots::{PyIter, SlotConstructor}, + slots::{IteratorIterable, PyIter, SlotConstructor}, IdProtocol, IntoPyObject, PyObjectRef, PyRef, PyResult, PyValue, PyWeakRef, TypeProtocol, VirtualMachine, }; @@ -54,6 +54,7 @@ mod decl { .into_ref_with_type(vm, cls) } } + impl IteratorIterable for PyItertoolsChain {} impl PyIter for PyItertoolsChain { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { loop { @@ -129,6 +130,7 @@ mod decl { #[pyimpl(with(PyIter, SlotConstructor))] impl PyItertoolsCompress {} + impl IteratorIterable for PyItertoolsCompress {} impl PyIter for PyItertoolsCompress { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { loop { @@ -187,6 +189,7 @@ mod decl { #[pyimpl(with(PyIter, SlotConstructor))] impl PyItertoolsCount {} + impl IteratorIterable for PyItertoolsCount {} impl PyIter for PyItertoolsCount { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let mut cur = zelf.cur.write(); @@ -222,6 +225,7 @@ mod decl { #[pyimpl(with(PyIter, SlotConstructor))] impl PyItertoolsCycle {} + impl IteratorIterable for PyItertoolsCycle {} impl PyIter for PyItertoolsCycle { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let item = if let Some(item) = get_next_object(vm, &zelf.iter)? { @@ -323,6 +327,7 @@ mod decl { } } + impl IteratorIterable for PyItertoolsRepeat {} impl PyIter for PyItertoolsRepeat { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { if let Some(ref times) = zelf.times { @@ -368,6 +373,7 @@ mod decl { #[pyimpl(with(PyIter, SlotConstructor))] impl PyItertoolsStarmap {} + impl IteratorIterable for PyItertoolsStarmap {} impl PyIter for PyItertoolsStarmap { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let obj = call_next(vm, &zelf.iter)?; @@ -418,6 +424,7 @@ mod decl { #[pyimpl(with(PyIter, SlotConstructor))] impl PyItertoolsTakewhile {} + impl IteratorIterable for PyItertoolsTakewhile {} impl PyIter for PyItertoolsTakewhile { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { if zelf.stop_flag.load() { @@ -480,6 +487,7 @@ mod decl { #[pyimpl(with(PyIter, SlotConstructor))] impl PyItertoolsDropwhile {} + impl IteratorIterable for PyItertoolsDropwhile {} impl PyIter for PyItertoolsDropwhile { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let predicate = &zelf.predicate; @@ -584,6 +592,7 @@ mod decl { Ok((new_value, new_key)) } } + impl IteratorIterable for PyItertoolsGroupBy {} impl PyIter for PyItertoolsGroupBy { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let mut state = zelf.state.lock(); @@ -633,6 +642,7 @@ mod decl { #[pyimpl(with(PyIter))] impl PyItertoolsGrouper {} + impl IteratorIterable for PyItertoolsGrouper {} impl PyIter for PyItertoolsGrouper { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let old_key = { @@ -762,6 +772,7 @@ mod decl { } } + impl IteratorIterable for PyItertoolsIslice {} impl PyIter for PyItertoolsIslice { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { while zelf.cur.load() < zelf.next.load() { @@ -825,6 +836,7 @@ mod decl { #[pyimpl(with(PyIter, SlotConstructor))] impl PyItertoolsFilterFalse {} + impl IteratorIterable for PyItertoolsFilterFalse {} impl PyIter for PyItertoolsFilterFalse { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let predicate = &zelf.predicate; @@ -883,6 +895,7 @@ mod decl { #[pyimpl(with(PyIter, SlotConstructor))] impl PyItertoolsAccumulate {} + impl IteratorIterable for PyItertoolsAccumulate {} impl PyIter for PyItertoolsAccumulate { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let iterable = &zelf.iterable; @@ -1001,6 +1014,7 @@ mod decl { .into_object()) } } + impl IteratorIterable for PyItertoolsTee {} impl PyIter for PyItertoolsTee { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let value = zelf.tee_data.get_item(vm, zelf.index.load())?; @@ -1076,6 +1090,7 @@ mod decl { } } } + impl IteratorIterable for PyItertoolsProduct {} impl PyIter for PyItertoolsProduct { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { // stop signal @@ -1154,6 +1169,7 @@ mod decl { #[pyimpl(with(PyIter, SlotConstructor))] impl PyItertoolsCombinations {} + impl IteratorIterable for PyItertoolsCombinations {} impl PyIter for PyItertoolsCombinations { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { // stop signal @@ -1244,6 +1260,7 @@ mod decl { #[pyimpl(with(PyIter, SlotConstructor))] impl PyItertoolsCombinationsWithReplacement {} + impl IteratorIterable for PyItertoolsCombinationsWithReplacement {} impl PyIter for PyItertoolsCombinationsWithReplacement { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { // stop signal @@ -1351,6 +1368,7 @@ mod decl { #[pyimpl(with(PyIter, SlotConstructor))] impl PyItertoolsPermutations {} + impl IteratorIterable for PyItertoolsPermutations {} impl PyIter for PyItertoolsPermutations { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { // stop signal @@ -1452,6 +1470,7 @@ mod decl { #[pyimpl(with(PyIter, SlotConstructor))] impl PyItertoolsZipLongest {} + impl IteratorIterable for PyItertoolsZipLongest {} impl PyIter for PyItertoolsZipLongest { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { if zelf.iterators.is_empty() { @@ -1505,6 +1524,7 @@ mod decl { #[pyimpl(with(PyIter, SlotConstructor))] impl PyItertoolsPairwise {} + impl IteratorIterable for PyItertoolsPairwise {} impl PyIter for PyItertoolsPairwise { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let old = match zelf.old.read().clone() { diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index af0427c33c..5aafdc5f45 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -374,7 +374,7 @@ pub(super) mod _os { byteslike::ArgBytesLike, exceptions::IntoPyException, function::{FuncArgs, OptionalArg}, - slots::PyIter, + slots::{IteratorIterable, PyIter}, suppress_iph, utils::Either, vm::{ReprGuard, VirtualMachine}, @@ -838,6 +838,7 @@ pub(super) mod _os { zelf.close() } } + impl IteratorIterable for ScandirIterator {} impl PyIter for ScandirIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { if zelf.exhausted.load() { diff --git a/vm/src/stdlib/pystruct.rs b/vm/src/stdlib/pystruct.rs index 45bad49f02..2c023ea17e 100644 --- a/vm/src/stdlib/pystruct.rs +++ b/vm/src/stdlib/pystruct.rs @@ -20,7 +20,7 @@ pub(crate) mod _struct { common::str::wchar_t, exceptions::PyBaseExceptionRef, function::PosArgs, - slots::{PyIter, SlotConstructor}, + slots::{IteratorIterable, PyIter, SlotConstructor}, utils::Either, IntoPyObject, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, VirtualMachine, }; @@ -832,6 +832,7 @@ pub(crate) mod _struct { self.buffer.len().saturating_sub(self.offset.load()) / self.format_spec.size } } + impl IteratorIterable for UnpackIterator {} impl PyIter for UnpackIterator { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { let size = zelf.format_spec.size; diff --git a/wasm/lib/src/js_module.rs b/wasm/lib/src/js_module.rs index 676e5e603a..8e0ca7c21e 100644 --- a/wasm/lib/src/js_module.rs +++ b/wasm/lib/src/js_module.rs @@ -9,7 +9,7 @@ use wasm_bindgen_futures::{future_to_promise, JsFuture}; use rustpython_vm::builtins::{PyFloatRef, PyStrRef, PyTypeRef}; use rustpython_vm::exceptions::PyBaseExceptionRef; use rustpython_vm::function::{OptionalArg, OptionalOption, PosArgs}; -use rustpython_vm::slots::PyIter; +use rustpython_vm::slots::{IteratorIterable, PyIter}; use rustpython_vm::types::create_simple_type; use rustpython_vm::VirtualMachine; use rustpython_vm::{ @@ -587,6 +587,7 @@ impl AwaitPromise { } } +impl IteratorIterable for AwaitPromise {} impl PyIter for AwaitPromise { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { zelf.send(None, vm)