diff --git a/vm/src/builtins/dict.rs b/vm/src/builtins/dict.rs index c35b100c7..a65dc47a7 100644 --- a/vm/src/builtins/dict.rs +++ b/vm/src/builtins/dict.rs @@ -12,7 +12,7 @@ use crate::{ IdProtocol, IntoPyObject, ItemProtocol, PyArithmeticValue::*, PyAttributes, PyClassDef, PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, - PyResult, PyValue, TryFromObject, TypeProtocol, + PyResult, PyValue, TryFromBorrowedObject, TypeProtocol, }; use crossbeam_utils::atomic::AtomicCell; use std::fmt; @@ -902,25 +902,27 @@ pub(crate) fn init(context: &PyContext) { PyDictReverseItemIterator::extend_class(context, &context.types.dict_reverseitemiterator_type); } +#[allow(clippy::type_complexity)] pub struct PyMapping { - dict: PyDictRef, + pub length: Option PyResult>, + pub subscript: Option PyResult>, + pub ass_subscript: + Option PyResult<()>>, } -impl TryFromObject for PyMapping { - fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - let dict = vm.ctx.new_dict(); - PyDict::merge( - &dict.entries, - OptionalArg::Present(obj), - KwArgs::default(), - vm, - )?; - Ok(PyMapping { dict }) - } -} +impl PyMapping {} -impl PyMapping { - pub fn into_dict(self) -> PyDictRef { - self.dict +impl TryFromBorrowedObject for PyMapping { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult { + let obj_cls = obj.class(); + for cls in obj_cls.iter_mro() { + if let Some(f) = cls.slots.as_mapping.load() { + return f(obj, vm); + } + } + Err(vm.new_type_error(format!( + "a dict-like object is required, not '{}'", + obj_cls.name() + ))) } } diff --git a/vm/src/slots.rs b/vm/src/slots.rs index f2b668043..c63e1b144 100644 --- a/vm/src/slots.rs +++ b/vm/src/slots.rs @@ -543,7 +543,38 @@ pub trait AsMapping: PyValue { Self::as_mapping(zelf, vm) } + fn downcast(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult> { + zelf.downcast::().map_err(|obj| { + vm.new_type_error(format!( + "{} type is required, not {}", + Self::class(vm), + obj.class() + )) + }) + } + + fn downcast_ref<'a>(zelf: &'a PyObjectRef, vm: &VirtualMachine) -> PyResult<&'a PyRef> { + zelf.downcast_ref::().ok_or_else(|| { + vm.new_type_error(format!( + "{} type is required, not {}", + Self::class(vm), + zelf.class() + )) + }) + } + fn as_mapping(zelf: &PyRef, vm: &VirtualMachine) -> PyResult; + + fn length(zelf: PyObjectRef, _vm: &VirtualMachine) -> PyResult; + + fn subscript(zelf: PyObjectRef, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult; + + fn ass_subscript( + zelf: PyObjectRef, + needle: PyObjectRef, + value: PyObjectRef, + vm: &VirtualMachine, + ) -> PyResult<()>; } #[pyimpl]