diff --git a/src/lib.rs b/src/lib.rs index 872ed37b7..142f79615 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -649,7 +649,7 @@ fn get_importer(path: &str, vm: &VirtualMachine) -> PyResult let path = vm.ctx.new_str(path); let path_hooks = vm.sys_module.clone().get_attr("path_hooks", vm)?; let mut importer = None; - let path_hooks: Vec = vm.extract_elements(&path_hooks)?; + let path_hooks: Vec = path_hooks.try_into_value(vm)?; for path_hook in path_hooks { match vm.invoke(&path_hook, (path.clone(),)) { Ok(imp) => { diff --git a/stdlib/src/math.rs b/stdlib/src/math.rs index e74af7030..42d150fd0 100644 --- a/stdlib/src/math.rs +++ b/stdlib/src/math.rs @@ -4,7 +4,7 @@ pub(crate) use math::make_module; mod math { use crate::vm::{ builtins::{try_bigint_to_f64, try_f64_to_bigint, PyFloat, PyInt, PyIntRef}, - function::{ArgIntoFloat, ArgIterable, ArgSequence, OptionalArg, PosArgs}, + function::{ArgIntoFloat, ArgIterable, OptionalArg, PosArgs}, utils::Either, PyObject, PyObjectRef, PyRef, PyResult, TypeProtocol, VirtualMachine, }; @@ -288,16 +288,12 @@ mod math { } #[pyfunction] - fn dist( - p: ArgSequence, - q: ArgSequence, - vm: &VirtualMachine, - ) -> PyResult { + fn dist(p: Vec, q: Vec, vm: &VirtualMachine) -> PyResult { let mut max = 0.0; let mut has_nan = false; - let p = ArgIntoFloat::vec_into_f64(p.into_vec()); - let q = ArgIntoFloat::vec_into_f64(q.into_vec()); + let p = ArgIntoFloat::vec_into_f64(p); + let q = ArgIntoFloat::vec_into_f64(q); let mut diffs = vec![]; if p.len() != q.len() { diff --git a/stdlib/src/resource.rs b/stdlib/src/resource.rs index fb5d418ab..bad79e6a8 100644 --- a/stdlib/src/resource.rs +++ b/stdlib/src/resource.rs @@ -130,7 +130,7 @@ mod resource { struct Limits(libc::rlimit); impl TryFromBorrowedObject for Limits { fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { - let seq = vm.extract_elements::(obj)?; + let seq: Vec = obj.try_to_value(vm)?; match *seq { [cur, max] => Ok(Self(libc::rlimit { rlim_cur: cur & RLIM_INFINITY, diff --git a/stdlib/src/select.rs b/stdlib/src/select.rs index 128dc90e9..226250efb 100644 --- a/stdlib/src/select.rs +++ b/stdlib/src/select.rs @@ -1,4 +1,6 @@ -use crate::vm::{builtins::PyListRef, PyObjectRef, PyResult, TryFromObject, VirtualMachine}; +use crate::vm::{ + builtins::PyListRef, PyObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine, +}; use std::{io, mem}; pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef { @@ -182,8 +184,8 @@ mod decl { } let deadline = timeout.map(|s| time::time(vm).unwrap() + s); - let seq2set = |list| -> PyResult<(Vec, FdSet)> { - let v = vm.extract_elements::(list)?; + let seq2set = |list: &PyObject| -> PyResult<(Vec, FdSet)> { + let v: Vec = list.try_to_value(vm)?; let mut fds = FdSet::new(); for fd in &v { fds.insert(fd.fno); diff --git a/vm/src/builtins/list.rs b/vm/src/builtins/list.rs index 84031715f..346504d58 100644 --- a/vm/src/builtins/list.rs +++ b/vm/src/builtins/list.rs @@ -99,7 +99,7 @@ impl PyList { #[pymethod] pub(crate) fn extend(&self, x: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - let mut new_elements = vm.extract_elements(&x)?; + let mut new_elements = x.try_to_value(vm)?; self.borrow_vec_mut().append(&mut new_elements); Ok(()) } @@ -350,7 +350,7 @@ impl PyList { #[pymethod(magic)] fn init(&self, iterable: OptionalArg, vm: &VirtualMachine) -> PyResult<()> { let mut elements = if let OptionalArg::Present(iterable) = iterable { - vm.extract_elements(&iterable)? + iterable.try_to_value(vm)? } else { vec![] }; diff --git a/vm/src/builtins/set.rs b/vm/src/builtins/set.rs index 54b0ee7c8..d04ff1315 100644 --- a/vm/src/builtins/set.rs +++ b/vm/src/builtins/set.rs @@ -704,7 +704,7 @@ impl Constructor for PyFrozenSet { } else { iterable }; - vm.extract_elements(&iterable)? + iterable.try_to_value(vm)? } else { vec![] }; diff --git a/vm/src/builtins/tuple.rs b/vm/src/builtins/tuple.rs index 8f26ba137..7256c36e7 100644 --- a/vm/src/builtins/tuple.rs +++ b/vm/src/builtins/tuple.rs @@ -102,7 +102,7 @@ impl Constructor for PyTuple { } else { iterable }; - vm.extract_elements(&iterable)? + iterable.try_to_value(vm)? } else { vec![] }; diff --git a/vm/src/convert.rs b/vm/src/convert.rs index dbd7e64cc..2e723d4fd 100644 --- a/vm/src/convert.rs +++ b/vm/src/convert.rs @@ -119,3 +119,9 @@ impl TryFromObject for Option { } } } + +impl TryFromBorrowedObject for Vec { + fn try_from_borrowed_object(vm: &VirtualMachine, value: &PyObject) -> PyResult { + vm.extract_elements_with(value, |obj| T::try_from_object(vm, obj)) + } +} diff --git a/vm/src/frame.rs b/vm/src/frame.rs index f1c1b4415..c6ab7b2c0 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -1032,7 +1032,7 @@ impl ExecutingFrame<'_> { } bytecode::Instruction::UnpackSequence { size } => { let value = self.pop_value(); - let elements = vm.extract_elements(&value).map_err(|e| { + let elements: Vec<_> = value.try_to_value(vm).map_err(|e| { if e.class().is(&vm.ctx.exceptions.type_error) { vm.new_type_error(format!( "cannot unpack non-iterable {} object", @@ -1121,9 +1121,10 @@ impl ExecutingFrame<'_> { ) -> PyResult> { let elements = self.pop_multiple(size); if unpack { - let mut result: Vec = vec![]; + let mut result = Vec::::new(); for element in elements { - result.extend(vm.extract_elements(&element)?); + let items: Vec<_> = element.try_to_value(vm)?; + result.extend(items); } Ok(result) } else { @@ -1172,7 +1173,7 @@ impl ExecutingFrame<'_> { if let Some(dict) = module.dict() { let filter_pred: Box bool> = if let Ok(all) = dict.get_item("__all__", vm) { - let all: Vec = vm.extract_elements(&all)?; + let all: Vec = all.try_to_value(vm)?; let all: Vec = all .into_iter() .map(|name| name.as_str().to_owned()) @@ -1384,7 +1385,7 @@ impl ExecutingFrame<'_> { IndexMap::new() }; let args = self.pop_value(); - let args = vm.extract_elements(&args)?; + let args = args.try_to_value(vm)?; Ok(FuncArgs { args, kwargs }) } @@ -1497,7 +1498,7 @@ impl ExecutingFrame<'_> { fn execute_unpack_ex(&mut self, vm: &VirtualMachine, before: u8, after: u8) -> FrameResult { let (before, after) = (before as usize, after as usize); let value = self.pop_value(); - let mut elements = vm.extract_elements::(&value)?; + let elements: Vec<_> = value.try_to_value(vm)?; let min_expected = before + after; let middle = elements.len().checked_sub(min_expected).ok_or_else(|| { @@ -1508,6 +1509,7 @@ impl ExecutingFrame<'_> { )) })?; + let mut elements = elements; // Elements on stack from right-to-left: self.state .stack diff --git a/vm/src/function/argument.rs b/vm/src/function/argument.rs index 5027b5bbb..672271a18 100644 --- a/vm/src/function/argument.rs +++ b/vm/src/function/argument.rs @@ -150,8 +150,9 @@ impl ArgSequence { &self.0 } } + impl TryFromObject for ArgSequence { fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - vm.extract_elements(&obj).map(Self) + obj.try_to_value(vm).map(Self) } } diff --git a/vm/src/protocol/mapping.rs b/vm/src/protocol/mapping.rs index da2fb020e..e844d4202 100644 --- a/vm/src/protocol/mapping.rs +++ b/vm/src/protocol/mapping.rs @@ -155,8 +155,6 @@ impl PyMapping<'_> { // TODO // PySequence::from(&iter).list(vm).map(|x| x.into()) - vm.ctx - .new_list(vm.extract_elements(&iter)?) - .into_pyresult(vm) + vm.ctx.new_list(iter.try_to_value(vm)?).into_pyresult(vm) } } diff --git a/vm/src/protocol/sequence.rs b/vm/src/protocol/sequence.rs index ed491d700..ffe3137aa 100644 --- a/vm/src/protocol/sequence.rs +++ b/vm/src/protocol/sequence.rs @@ -289,7 +289,7 @@ impl PySequence<'_> { } pub fn list(&self, vm: &VirtualMachine) -> PyResult { - let list = vm.ctx.new_list(vm.extract_elements(self.obj)?); + let list = vm.ctx.new_list(self.obj.try_to_value(vm)?); Ok(list) } diff --git a/vm/src/stdlib/ast.rs b/vm/src/stdlib/ast.rs index 9139cd6a8..b01e54e7c 100644 --- a/vm/src/stdlib/ast.rs +++ b/vm/src/stdlib/ast.rs @@ -36,7 +36,7 @@ mod _ast { fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { let obj: PyObjectRef = zelf.clone_class().into(); let fields = obj.get_attr("_fields", vm)?; - let fields = vm.extract_elements::(&fields)?; + let fields: Vec = fields.try_to_value(vm)?; let numargs = args.args.len(); if numargs > fields.len() { return Err(vm.new_type_error(format!( diff --git a/vm/src/stdlib/builtins.rs b/vm/src/stdlib/builtins.rs index d94ff442a..bf53b0225 100644 --- a/vm/src/stdlib/builtins.rs +++ b/vm/src/stdlib/builtins.rs @@ -457,7 +457,7 @@ mod builtins { } args.args } - std::cmp::Ordering::Equal => vm.extract_elements(&args.args[0])?, + std::cmp::Ordering::Equal => args.args[0].try_to_value(vm)?, std::cmp::Ordering::Less => { // zero arguments means type error: return Err(vm.new_type_error("Expected 1 or more arguments".to_owned())); @@ -735,7 +735,7 @@ mod builtins { #[pyfunction] fn sorted(iterable: PyObjectRef, opts: SortOptions, vm: &VirtualMachine) -> PyResult { - let items = vm.extract_elements(&iterable)?; + let items: Vec<_> = iterable.try_to_value(vm)?; let lst = PyList::from(items); lst.sort(opts, vm)?; Ok(lst) diff --git a/vm/src/stdlib/collections.rs b/vm/src/stdlib/collections.rs index 66e1667dd..a59909ae0 100644 --- a/vm/src/stdlib/collections.rs +++ b/vm/src/stdlib/collections.rs @@ -91,7 +91,7 @@ mod _collections { let elements = iterable .into_option() .map(|iter| { - let mut elements: Vec = vm.extract_elements(&iter)?; + let mut elements: Vec = iter.try_to_value(vm)?; if let Some(maxlen) = maxlen { elements.drain(..elements.len().saturating_sub(maxlen)); } @@ -177,7 +177,7 @@ mod _collections { fn _extend(&self, iter: &PyObject, vm: &VirtualMachine) -> PyResult<()> { self.state.fetch_add(1); let max_len = self.maxlen; - let mut elements: Vec = vm.extract_elements(iter)?; + let mut elements: Vec = iter.try_to_value(vm)?; if let Some(max_len) = max_len { if max_len > elements.len() { let mut deque = self.borrow_deque_mut(); @@ -195,7 +195,7 @@ mod _collections { #[pymethod] fn extendleft(&self, iter: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { let max_len = self.maxlen; - let mut elements: Vec = vm.extract_elements(&iter)?; + let mut elements: Vec = iter.try_to_value(vm)?; elements.reverse(); if let Some(max_len) = max_len { diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 50bc1802f..3e286b294 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -451,7 +451,7 @@ mod _io { ) -> PyResult> { let hint = hint.flatten().unwrap_or(-1); if hint <= 0 { - return vm.extract_elements(&instance); + return instance.try_to_value(vm); } let hint = hint as usize; let mut ret = Vec::new(); diff --git a/vm/src/stdlib/itertools.rs b/vm/src/stdlib/itertools.rs index b2d040f45..04f539027 100644 --- a/vm/src/stdlib/itertools.rs +++ b/vm/src/stdlib/itertools.rs @@ -48,7 +48,7 @@ mod decl { vm: &VirtualMachine, ) -> PyResult> { PyItertoolsChain { - iterables: vm.extract_elements(&iterable)?, + iterables: iterable.try_to_value(vm)?, cur_idx: AtomicCell::new(0), cached_iter: PyRwLock::new(None), } @@ -366,7 +366,8 @@ mod decl { let function = &zelf.function; match obj { PyIterReturn::Return(obj) => { - PyIterReturn::from_pyresult(vm.invoke(function, vm.extract_elements(&obj)?), vm) + let args: Vec<_> = obj.try_to_value(vm)?; + PyIterReturn::from_pyresult(vm.invoke(function, args), vm) } PyIterReturn::StopIteration(v) => Ok(PyIterReturn::StopIteration(v)), } @@ -1075,7 +1076,7 @@ mod decl { let repeat = args.repeat.unwrap_or(1); let mut pools = Vec::new(); for arg in iterables.iter() { - pools.push(vm.extract_elements(arg)?); + pools.push(arg.try_to_value(vm)?); } let pools = std::iter::repeat(pools) .take(repeat) @@ -1176,7 +1177,7 @@ mod decl { Self::Args { iterable, r }: Self::Args, vm: &VirtualMachine, ) -> PyResult { - let pool = vm.extract_elements(&iterable)?; + let pool: Vec<_> = iterable.try_to_value(vm)?; let r = r.as_bigint(); if r.is_negative() { @@ -1267,7 +1268,7 @@ mod decl { Self::Args { iterable, r }: Self::Args, vm: &VirtualMachine, ) -> PyResult { - let pool = vm.extract_elements(&iterable)?; + let pool: Vec<_> = iterable.try_to_value(vm)?; let r = r.as_bigint(); if r.is_negative() { return Err(vm.new_value_error("r must be non-negative".to_owned())); @@ -1363,7 +1364,7 @@ mod decl { Self::Args { iterable, r }: Self::Args, vm: &VirtualMachine, ) -> PyResult { - let pool = vm.extract_elements(&iterable)?; + let pool: Vec<_> = iterable.try_to_value(vm)?; let n = pool.len(); // If r is not provided, r == n. If provided, r must be a positive integer, or None. diff --git a/vm/src/stdlib/posix.rs b/vm/src/stdlib/posix.rs index d80fe1ad0..2b2c153f5 100644 --- a/vm/src/stdlib/posix.rs +++ b/vm/src/stdlib/posix.rs @@ -30,7 +30,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef { pub mod module { use crate::{ builtins::{PyDictRef, PyInt, PyIntRef, PyListRef, PyStrRef, PyTupleRef, PyTypeRef}, - function::{IntoPyException, IntoPyObject, OptionalArg}, + function::{ArgBytesLike, IntoPyException, IntoPyObject, OptionalArg}, stdlib::os::{ errno_err, DirFd, FollowSymlinks, PathOrFd, PyPathLike, SupportFunc, TargetIsDirectory, _os, fs_metadata, IOErrorBuilder, @@ -1929,19 +1929,14 @@ pub mod module { fn _extract_vec_bytes( x: OptionalArg, vm: &VirtualMachine, - ) -> PyResult>> { - let inner = match x.into_option() { - Some(v) => { - let v = vm.extract_elements::(&v)?; - if v.is_empty() { - None - } else { - Some(v) - } - } - None => None, - }; - Ok(inner) + ) -> PyResult>> { + x.into_option() + .map(|x| { + let v: Vec = x.try_to_value(vm)?; + Ok(if v.is_empty() { None } else { Some(v) }) + }) + .transpose() + .map(Option::flatten) } #[cfg(target_os = "macos")] diff --git a/vm/src/stdlib/sre.rs b/vm/src/stdlib/sre.rs index bd67a805c..9c41cfcb2 100644 --- a/vm/src/stdlib/sre.rs +++ b/vm/src/stdlib/sre.rs @@ -83,13 +83,14 @@ mod _sre { // isbytes will be hanging (-1) // here is just a hack to let re.Scanner works only with str not bytes let isbytes = !vm.is_none(&pattern) && !pattern.payload_is::(); + let code = code.try_to_value(vm)?; Ok(Pattern { pattern, flags: SreFlag::from_bits_truncate(flags), - code: vm.extract_elements::(&code)?, + code, groups, groupindex, - indexgroup: vm.extract_elements(&indexgroup)?, + indexgroup: indexgroup.try_to_value(vm)?, isbytes, }) } diff --git a/vm/src/stdlib/time.rs b/vm/src/stdlib/time.rs index 940f2197c..9c7cf7493 100644 --- a/vm/src/stdlib/time.rs +++ b/vm/src/stdlib/time.rs @@ -377,7 +377,7 @@ mod time { impl TryFromObject for PyStructTime { fn try_from_object(vm: &VirtualMachine, seq: PyObjectRef) -> PyResult { - let seq = vm.extract_elements::(&seq)?; + let seq: Vec<_> = seq.try_to_value(vm)?; if seq.len() != 9 { return Err( vm.new_type_error("time.struct_time() takes a sequence of length 9".to_owned()) diff --git a/vm/src/suggestion.rs b/vm/src/suggestion.rs index b936bcb17..5ac4b95d6 100644 --- a/vm/src/suggestion.rs +++ b/vm/src/suggestion.rs @@ -62,12 +62,12 @@ pub fn offer_suggestions(exc: &PyBaseExceptionRef, vm: &VirtualMachine) -> Optio return Some(suggestions); }; - let globals = vm.extract_elements(tb.frame.globals.as_object()).ok()?; + let globals: Vec<_> = tb.frame.globals.as_object().try_to_value(vm).ok()?; if let Some(suggestions) = calculate_suggestions(globals.as_slice().iter(), &name) { return Some(suggestions); }; - let builtins = vm.extract_elements(tb.frame.builtins.as_object()).ok()?; + let builtins: Vec<_> = tb.frame.builtins.as_object().try_to_value(vm).ok()?; calculate_suggestions(builtins.as_slice().iter(), &name) } else { None diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 2e1548875..59ab75d13 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -25,7 +25,7 @@ use crate::{ pyobject::PyLease, scope::Scope, signal, stdlib, IdProtocol, PyContext, PyObject, PyObjectRef, PyObjectWrap, PyRef, PyRefExact, - PyResult, PyValue, TryFromObject, TypeProtocol, + PyResult, PyValue, TypeProtocol, }; use crossbeam_utils::atomic::AtomicCell; use std::{ @@ -648,10 +648,6 @@ impl VirtualMachine { slice.iter().map(|obj| func(obj.clone())).collect() } - pub fn extract_elements(&self, value: &PyObject) -> PyResult> { - self.extract_elements_with(value, |obj| T::try_from_object(self, obj)) - } - pub fn map_iterable_object(&self, obj: &PyObject, mut f: F) -> PyResult>> where F: FnMut(PyObjectRef) -> PyResult, diff --git a/vm/src/vm_object.rs b/vm/src/vm_object.rs index e4fe7eb51..3d2c3200c 100644 --- a/vm/src/vm_object.rs +++ b/vm/src/vm_object.rs @@ -133,7 +133,7 @@ impl VirtualMachine { .invoke((), self)?, None => self.call_method(self.current_locals()?.as_object(), "keys", ())?, }; - let items = self.extract_elements(&seq)?; + let items: Vec<_> = seq.try_to_value(self)?; let lst = PyList::from(items); lst.sort(Default::default(), self)?; Ok(lst)