Skip to content

Commit 4546661

Browse files
committed
&'static PySequenceMethods
1 parent 4d02fe0 commit 4546661

File tree

7 files changed

+123
-139
lines changed

7 files changed

+123
-139
lines changed

vm/src/builtins/iter.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use rustpython_common::{
1414
lock::{PyMutex, PyRwLock, PyRwLockUpgradableReadGuard},
1515
static_cell,
1616
};
17-
use std::borrow::Cow;
1817

1918
/// Marks status of iterator.
2019
#[derive(Debug, Clone)]
@@ -163,7 +162,7 @@ pub fn builtins_reversed(vm: &VirtualMachine) -> &PyObject {
163162
#[derive(Debug)]
164163
pub struct PySequenceIterator {
165164
// cached sequence methods
166-
seq_methods: Cow<'static, PySequenceMethods>,
165+
seq_methods: &'static PySequenceMethods,
167166
internal: PyMutex<PositionIterInternal<PyObjectRef>>,
168167
}
169168

@@ -177,9 +176,8 @@ impl PyPayload for PySequenceIterator {
177176
impl PySequenceIterator {
178177
pub fn new(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<Self> {
179178
let seq = PySequence::try_protocol(obj.as_ref(), vm)?;
180-
let seq_methods = seq.methods_cow(vm).clone();
181179
Ok(Self {
182-
seq_methods,
180+
seq_methods: seq.methods,
183181
internal: PyMutex::new(PositionIterInternal::new(obj, 0)),
184182
})
185183
}
@@ -188,7 +186,7 @@ impl PySequenceIterator {
188186
fn length_hint(&self, vm: &VirtualMachine) -> PyObjectRef {
189187
let internal = self.internal.lock();
190188
if let IterStatus::Active(obj) = &internal.status {
191-
let seq = PySequence::with_methods(obj, self.seq_methods.clone());
189+
let seq = PySequence::with_methods(obj, self.seq_methods);
192190
seq.length(vm)
193191
.map(|x| PyInt::from(x).into_pyobject(vm))
194192
.unwrap_or_else(|_| vm.ctx.not_implemented())
@@ -212,7 +210,7 @@ impl IterNextIterable for PySequenceIterator {}
212210
impl IterNext for PySequenceIterator {
213211
fn next(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
214212
zelf.internal.lock().next(|obj, pos| {
215-
let seq = PySequence::with_methods(obj, zelf.seq_methods.clone());
213+
let seq = PySequence::with_methods(obj, zelf.seq_methods);
216214
PyIterReturn::from_getitem_result(seq.get_item(pos as isize, vm), vm)
217215
})
218216
}

vm/src/builtins/list.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ impl PyList {
139139
}
140140

141141
fn inplace_concat(zelf: &Py<Self>, other: &PyObject, vm: &VirtualMachine) -> PyObjectRef {
142-
if let Ok(mut seq) = PySequence::from(other).extract_cloned(Ok, vm) {
142+
if let Ok(mut seq) = extract_cloned(other, Ok, vm) {
143143
zelf.borrow_vec_mut().append(&mut seq);
144144
zelf.to_owned().into()
145145
} else {
@@ -149,7 +149,7 @@ impl PyList {
149149

150150
#[pymethod(magic)]
151151
fn iadd(zelf: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
152-
if let Ok(mut seq) = PySequence::from(other.as_ref()).extract_cloned(Ok, vm) {
152+
if let Ok(mut seq) = extract_cloned(&*other, Ok, vm) {
153153
zelf.borrow_vec_mut().append(&mut seq);
154154
zelf.into()
155155
} else {
@@ -215,7 +215,7 @@ impl PyList {
215215
match SequenceIndex::try_from_borrowed_object(vm, needle)? {
216216
SequenceIndex::Int(index) => self.borrow_vec_mut().set_item_by_index(vm, index, value),
217217
SequenceIndex::Slice(slice) => {
218-
let sec = PySequence::from(value.as_ref()).extract_cloned(Ok, vm)?;
218+
let sec = extract_cloned(&*value, Ok, vm)?;
219219
self.borrow_vec_mut().set_item_by_slice(vm, slice, &sec)
220220
}
221221
}
@@ -352,6 +352,31 @@ impl PyList {
352352
}
353353
}
354354

355+
fn extract_cloned<F, R>(obj: &PyObject, mut f: F, vm: &VirtualMachine) -> PyResult<Vec<R>>
356+
where
357+
F: FnMut(PyObjectRef) -> PyResult<R>,
358+
{
359+
use crate::builtins::PyTuple;
360+
if let Some(tuple) = obj.payload_if_exact::<PyTuple>(vm) {
361+
tuple.iter().map(|x| f(x.clone())).collect()
362+
} else if let Some(list) = obj.payload_if_exact::<PyList>(vm) {
363+
list.borrow_vec().iter().map(|x| f(x.clone())).collect()
364+
} else {
365+
let iter = obj.to_owned().get_iter(vm)?;
366+
let iter = iter.iter::<PyObjectRef>(vm)?;
367+
let len = PySequence::new(obj, vm)
368+
.and_then(|seq| seq.length_opt(vm))
369+
.transpose()?
370+
.unwrap_or(0);
371+
let mut v = Vec::with_capacity(len);
372+
for x in iter {
373+
v.push(f(x?)?);
374+
}
375+
v.shrink_to_fit();
376+
Ok(v)
377+
}
378+
}
379+
355380
impl<'a> MutObjectSequenceOp<'a> for PyList {
356381
type Guard = PyMappedRwLockReadGuard<'a, [PyObjectRef]>;
357382

vm/src/builtins/mappingproxy.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ impl PyMappingProxy {
9191
MappingProxyInner::Class(class) => Ok(key
9292
.as_interned_str(vm)
9393
.map_or(false, |key| class.attributes.read().contains_key(key))),
94-
MappingProxyInner::Mapping(obj) => PySequence::from(obj.as_ref()).contains(key, vm),
94+
MappingProxyInner::Mapping(mapping) => PySequence::contains(&*mapping, key, vm),
9595
}
9696
}
9797

vm/src/protocol/mapping.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,7 @@ impl PyMapping<'_> {
6969
// PyMapping::Check
7070
#[inline]
7171
pub fn check(obj: &PyObject, vm: &VirtualMachine) -> bool {
72-
Self::find_methods(obj, vm)
73-
.and_then(|m| m.subscript)
74-
.is_some()
72+
Self::find_methods(obj, vm).map_or(false, PyMappingMethods::check)
7573
}
7674

7775
pub fn find_methods(obj: &PyObject, vm: &VirtualMachine) -> Option<&'static PyMappingMethods> {

vm/src/protocol/object.rs

+19-20
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,8 @@ impl PyObject {
522522
// int PyObject_TypeCheck(PyObject *o, PyTypeObject *type)
523523

524524
pub fn length_opt(&self, vm: &VirtualMachine) -> Option<PyResult<usize>> {
525-
PySequence::from(self)
526-
.length_opt(vm)
525+
PySequence::new(self, vm)
526+
.and_then(|seq| seq.length_opt(vm))
527527
.or_else(|| PyMapping::new(self, vm).and_then(|mapping| mapping.length_opt(vm)))
528528
}
529529

@@ -576,17 +576,17 @@ impl PyObject {
576576
return f(&mapping, &needle, Some(value), vm);
577577
}
578578
}
579-
580-
let seq = PySequence::from(self);
581-
if let Some(f) = seq.methods(vm).ass_item {
582-
let i = needle.key_as_isize(vm)?;
583-
f(&seq, i, Some(value), vm)
584-
} else {
585-
Err(vm.new_type_error(format!(
586-
"'{}' does not support item assignment",
587-
self.class()
588-
)))
579+
if let Some(seq) = PySequence::new(self, vm) {
580+
if let Some(f) = seq.methods.ass_item {
581+
let i = needle.key_as_isize(vm)?;
582+
return f(&seq, i, Some(value), vm);
583+
}
589584
}
585+
586+
Err(vm.new_type_error(format!(
587+
"'{}' does not support item assignment",
588+
self.class()
589+
)))
590590
}
591591

592592
pub fn del_item<K: DictKey + ?Sized>(&self, needle: &K, vm: &VirtualMachine) -> PyResult<()> {
@@ -600,14 +600,13 @@ impl PyObject {
600600
return f(&mapping, &needle, None, vm);
601601
}
602602
}
603-
604-
let seq = PySequence::from(self);
605-
606-
if let Some(f) = seq.methods(vm).ass_item {
607-
let i = needle.key_as_isize(vm)?;
608-
f(&seq, i, None, vm)
609-
} else {
610-
Err(vm.new_type_error(format!("'{}' does not support item deletion", self.class())))
603+
if let Some(seq) = PySequence::new(self, vm) {
604+
if let Some(f) = seq.methods.ass_item {
605+
let i = needle.key_as_isize(vm)?;
606+
return f(&seq, i, None, vm);
607+
}
611608
}
609+
610+
Err(vm.new_type_error(format!("'{}' does not support item deletion", self.class())))
612611
}
613612
}

0 commit comments

Comments
 (0)