From 8a2cd2ba08cc1f965ce3ef9c0b23db4f8a6699c7 Mon Sep 17 00:00:00 2001 From: Jeong Yunwon Date: Mon, 16 May 2022 07:41:53 +0900 Subject: [PATCH] Refactor DictKey - Remove &PyObject / PyObjectRef --- stdlib/src/bisect.rs | 4 +- stdlib/src/dis.rs | 8 +- vm/src/builtins/dict.rs | 87 +++++++------- vm/src/builtins/enumerate.rs | 2 +- vm/src/builtins/function.rs | 4 +- vm/src/builtins/function/jitfunc.rs | 2 +- vm/src/builtins/genericalias.rs | 2 +- vm/src/builtins/mappingproxy.rs | 2 +- vm/src/builtins/set.rs | 10 +- vm/src/builtins/str.rs | 15 ++- vm/src/dictdatatype.rs | 172 +++++++++++++++++----------- vm/src/format.rs | 6 +- vm/src/frame.rs | 32 +++--- vm/src/intern.rs | 3 +- vm/src/protocol/object.rs | 30 ++--- vm/src/py_serde.rs | 2 +- vm/src/stdlib/errno.rs | 4 +- vm/src/stdlib/imp.rs | 2 +- vm/src/stdlib/marshal.rs | 6 +- vm/src/stdlib/nt.rs | 4 +- vm/src/stdlib/operator.rs | 10 +- vm/src/stdlib/posix.rs | 2 +- vm/src/stdlib/posix_compat.rs | 2 +- vm/src/stdlib/sre.rs | 4 +- vm/src/stdlib/thread.rs | 4 +- vm/src/stdlib/weakref.rs | 2 +- vm/src/vm/method.rs | 2 +- vm/src/vm/mod.rs | 2 +- wasm/lib/src/vm_class.rs | 6 +- 29 files changed, 229 insertions(+), 202 deletions(-) diff --git a/stdlib/src/bisect.rs b/stdlib/src/bisect.rs index e5c2bb580..0fc89e904 100644 --- a/stdlib/src/bisect.rs +++ b/stdlib/src/bisect.rs @@ -74,7 +74,7 @@ mod _bisect { while lo < hi { // Handles issue 13496. let mid = (lo + hi) / 2; - if a.get_item(mid, vm)? + if a.get_item(&mid, vm)? .rich_compare_bool(&x, PyComparisonOp::Lt, vm)? { lo = mid + 1; @@ -104,7 +104,7 @@ mod _bisect { while lo < hi { // Handles issue 13496. let mid = (lo + hi) / 2; - if x.rich_compare_bool(&*a.get_item(mid, vm)?, PyComparisonOp::Lt, vm)? { + if x.rich_compare_bool(&*a.get_item(&mid, vm)?, PyComparisonOp::Lt, vm)? { hi = mid; } else { lo = mid + 1; diff --git a/stdlib/src/dis.rs b/stdlib/src/dis.rs index 094da6223..0a97a7bfa 100644 --- a/stdlib/src/dis.rs +++ b/stdlib/src/dis.rs @@ -33,8 +33,12 @@ mod decl { fn compiler_flag_names(vm: &VirtualMachine) -> PyDictRef { let dict = vm.ctx.new_dict(); for (name, flag) in CodeFlags::NAME_MAPPING { - dict.set_item(vm.new_pyobj(flag.bits()), vm.ctx.new_str(*name).into(), vm) - .unwrap(); + dict.set_item( + &*vm.new_pyobj(flag.bits()), + vm.ctx.new_str(*name).into(), + vm, + ) + .unwrap(); } dict } diff --git a/vm/src/builtins/dict.rs b/vm/src/builtins/dict.rs index 8b58bcca6..9c1f0e8ed 100644 --- a/vm/src/builtins/dict.rs +++ b/vm/src/builtins/dict.rs @@ -86,8 +86,8 @@ impl PyDict { if let Some(keys) = vm.get_method(other.clone(), "keys") { let keys = vm.invoke(&keys?, ())?.get_iter(vm)?; while let PyIterReturn::Return(key) = keys.next(vm)? { - let val = other.get_item(key.clone(), vm)?; - dict.insert(vm, key, val)?; + let val = other.get_item(&*key, vm)?; + dict.insert(vm, &*key, val)?; } } else { let iter = other.get_iter(vm)?; @@ -105,7 +105,7 @@ impl PyDict { if matches!(elem_iter.next(vm)?, PyIterReturn::Return(_)) { return Err(err(vm)); } - dict.insert(vm, key, value)?; + dict.insert(vm, &*key, value)?; } } Ok(()) @@ -118,7 +118,7 @@ impl PyDict { ) -> PyResult<()> { let dict_size = &dict_other.size(); for (key, value) in &dict_other { - dict.insert(vm, key, value)?; + dict.insert(vm, &*key, value)?; } if dict_other.entries.has_changed_size(dict_size) { return Err(vm.new_runtime_error("dict mutated during update".to_owned())); @@ -146,7 +146,7 @@ impl PyDict { (zelf, other) }; for (k, v1) in subset { - match superset.get_item_opt(k, vm)? { + match superset.get_item_opt(&*k, vm)? { Some(v2) => { if v1.is(&v2) { continue; @@ -169,18 +169,18 @@ impl PyDict { /// Set item variant which can be called with multiple /// key types, such as str to name a notable one. - pub(crate) fn inner_setitem( + pub(crate) fn inner_setitem( &self, - key: K, + key: &K, value: PyObjectRef, vm: &VirtualMachine, ) -> PyResult<()> { self.entries.insert(vm, key, value) } - pub(crate) fn inner_delitem( + pub(crate) fn inner_delitem( &self, - key: K, + key: &K, vm: &VirtualMachine, ) -> PyResult<()> { self.entries.delete(vm, key) @@ -192,22 +192,21 @@ impl PyDict { key: PyObjectRef, default: impl FnOnce() -> PyObjectRef, ) -> PyResult { - self.entries.setdefault(vm, key, default) + self.entries.setdefault(vm, &*key, default) } pub fn from_attributes(attrs: PyAttributes, vm: &VirtualMachine) -> PyResult { let dict = DictContentType::default(); for (key, value) in attrs { - dict.insert(vm, vm.new_pyobj(key), value)?; + dict.insert(vm, key.as_str(), value)?; } Ok(PyDict { entries: dict }) } - pub fn contains_key(&self, key: K, vm: &VirtualMachine) -> bool { - let key = key.to_pyobject(vm); - self.entries.contains(vm, &key).unwrap() + pub fn contains_key(&self, key: &K, vm: &VirtualMachine) -> bool { + self.entries.contains(vm, key).unwrap() } pub fn size(&self) -> dictdatatype::DictSize { @@ -263,7 +262,7 @@ impl PyDict { } Err(pyobj) => { for key in iterable.iter(vm)? { - pyobj.set_item(key?, value.clone(), vm)?; + pyobj.set_item(&*key?, value.clone(), vm)?; } Ok(pyobj) } @@ -304,12 +303,12 @@ impl PyDict { #[pymethod(magic)] fn contains(&self, key: PyObjectRef, vm: &VirtualMachine) -> PyResult { - self.entries.contains(vm, &key) + self.entries.contains(vm, &*key) } #[pymethod(magic)] fn delitem(&self, key: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - self.inner_delitem(key, vm) + self.inner_delitem(&*key, vm) } #[pymethod] @@ -334,13 +333,13 @@ impl PyDict { #[pymethod(magic)] fn setitem(&self, key: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - self.inner_setitem(key, value, vm) + self.inner_setitem(&*key, value, vm) } #[pymethod(magic)] #[cfg_attr(feature = "flame-it", flame("PyDictRef"))] fn getitem(zelf: PyRef, key: PyObjectRef, vm: &VirtualMachine) -> PyResult { - zelf.inner_getitem(key, vm) + zelf.inner_getitem(&*key, vm) } #[pymethod] @@ -350,7 +349,7 @@ impl PyDict { default: OptionalArg, vm: &VirtualMachine, ) -> PyResult { - match self.entries.get(vm, &key)? { + match self.entries.get(vm, &*key)? { Some(value) => Ok(value), None => Ok(default.unwrap_or_none(vm)), } @@ -364,7 +363,7 @@ impl PyDict { vm: &VirtualMachine, ) -> PyResult { self.entries - .setdefault(vm, key, || default.unwrap_or_none(vm)) + .setdefault(vm, &*key, || default.unwrap_or_none(vm)) } #[pymethod] @@ -385,7 +384,7 @@ impl PyDict { Self::merge_object(&self.entries, dict_obj, vm)?; } for (key, value) in kwargs.into_iter() { - self.entries.insert(vm, vm.new_pyobj(key), value)?; + self.entries.insert(vm, &key, value)?; } Ok(()) } @@ -425,7 +424,7 @@ impl PyDict { default: OptionalArg, vm: &VirtualMachine, ) -> PyResult { - match self.entries.pop(vm, &key)? { + match self.entries.pop(vm, &*key)? { Some(value) => Ok(value), None => default.ok_or_else(|| vm.new_key_error(key)), } @@ -523,25 +522,25 @@ impl Py { self.class().is(&vm.ctx.types.dict_type) } - fn missing_opt( + fn missing_opt( &self, - key: K, + key: &K, vm: &VirtualMachine, ) -> PyResult> { vm.get_method(self.to_owned().into(), "__missing__") - .map(|methods| vm.invoke(&methods?, (key,))) + .map(|methods| vm.invoke(&methods?, (key.to_pyobject(vm),))) .transpose() } #[inline] - fn inner_getitem( + fn inner_getitem( &self, - key: K, + key: &K, vm: &VirtualMachine, ) -> PyResult { - if let Some(value) = self.entries.get(vm, &key)? { + if let Some(value) = self.entries.get(vm, key)? { Ok(value) - } else if let Some(value) = self.missing_opt(key.clone(), vm)? { + } else if let Some(value) = self.missing_opt(key, vm)? { Ok(value) } else { Err(vm.new_key_error(key.to_pyobject(vm))) @@ -558,16 +557,16 @@ impl Py { attrs } - pub fn get_item_opt( + pub fn get_item_opt( &self, - key: K, + key: &K, vm: &VirtualMachine, ) -> PyResult> { if self.exact_dict(vm) { - self.entries.get(vm, &key) + self.entries.get(vm, key) // FIXME: check __missing__? } else { - match self.as_object().get_item(key.clone(), vm) { + match self.as_object().get_item(key, vm) { Ok(value) => Ok(Some(value)), Err(e) if e.fast_isinstance(&vm.ctx.exceptions.key_error) => { self.missing_opt(key, vm) @@ -577,11 +576,7 @@ impl Py { } } - pub fn get_item( - &self, - key: K, - vm: &VirtualMachine, - ) -> PyResult { + pub fn get_item(&self, key: &K, vm: &VirtualMachine) -> PyResult { if self.exact_dict(vm) { self.inner_getitem(key, vm) } else { @@ -589,9 +584,9 @@ impl Py { } } - pub fn set_item( + pub fn set_item( &self, - key: K, + key: &K, value: PyObjectRef, vm: &VirtualMachine, ) -> PyResult<()> { @@ -602,7 +597,7 @@ impl Py { } } - pub fn del_item(&self, key: K, vm: &VirtualMachine) -> PyResult<()> { + pub fn del_item(&self, key: &K, vm: &VirtualMachine) -> PyResult<()> { if self.exact_dict(vm) { self.inner_delitem(key, vm) } else { @@ -610,17 +605,17 @@ impl Py { } } - pub fn get_chain( + pub fn get_chain( &self, other: &Self, - key: K, + key: &K, vm: &VirtualMachine, ) -> PyResult> { let self_exact = self.exact_dict(vm); let other_exact = other.exact_dict(vm); if self_exact && other_exact { - self.entries.get_chain(&other.entries, vm, &key) - } else if let Some(value) = self.get_item_opt(key.clone(), vm)? { + self.entries.get_chain(&other.entries, vm, key) + } else if let Some(value) = self.get_item_opt(key, vm)? { Ok(Some(value)) } else { other.get_item_opt(key, vm) diff --git a/vm/src/builtins/enumerate.rs b/vm/src/builtins/enumerate.rs index c07b32a79..a71f0c51a 100644 --- a/vm/src/builtins/enumerate.rs +++ b/vm/src/builtins/enumerate.rs @@ -128,7 +128,7 @@ impl IterNext for PyReverseSequenceIterator { fn next(zelf: &crate::Py, vm: &VirtualMachine) -> PyResult { zelf.internal .lock() - .rev_next(|obj, pos| PyIterReturn::from_getitem_result(obj.get_item(pos, vm), vm)) + .rev_next(|obj, pos| PyIterReturn::from_getitem_result(obj.get_item(&pos, vm), vm)) } } diff --git a/vm/src/builtins/function.rs b/vm/src/builtins/function.rs index d77d37c1a..29ea3d991 100644 --- a/vm/src/builtins/function.rs +++ b/vm/src/builtins/function.rs @@ -137,7 +137,7 @@ impl PyFunction { } *slot = Some(value); } else if let Some(kwargs) = kwargs.as_ref() { - kwargs.set_item(name, value, vm)?; + kwargs.set_item(&name, value, vm)?; } else if argpos(0..code.posonlyarg_count, &name).is_some() { posonly_passed_as_kwarg.push(name); } else { @@ -242,7 +242,7 @@ impl PyFunction { .filter(|(slot, _)| slot.is_none()) { if let Some(defaults) = &get_defaults!().1 { - if let Some(default) = defaults.get_item_opt(kwarg.clone(), vm)? { + if let Some(default) = defaults.get_item_opt(&*kwarg, vm)? { *slot = Some(default); continue; } diff --git a/vm/src/builtins/function/jitfunc.rs b/vm/src/builtins/function/jitfunc.rs index f9f0fc605..6a5c8a558 100644 --- a/vm/src/builtins/function/jitfunc.rs +++ b/vm/src/builtins/function/jitfunc.rs @@ -188,7 +188,7 @@ pub(crate) fn get_jit_args<'a>( let arg_idx = i + func.code.arg_count; if !jit_args.is_set(arg_idx) { let default = kw_only_defaults - .get_item(name.clone(), vm) + .get_item(&*name, vm) .map_err(|_| ArgsError::NotAllArgsPassed) .and_then(|obj| get_jit_value(vm, &obj))?; jit_args.set(arg_idx, default)?; diff --git a/vm/src/builtins/genericalias.rs b/vm/src/builtins/genericalias.rs index 9227e8a36..7ef891b8a 100644 --- a/vm/src/builtins/genericalias.rs +++ b/vm/src/builtins/genericalias.rs @@ -249,7 +249,7 @@ fn subs_tvars( }) .collect::>(); let sub_args: PyObjectRef = PyTuple::new_ref(sub_args, &vm.ctx).into(); - Some(obj.get_item(sub_args, vm)) + Some(obj.get_item(&*sub_args, vm)) } else { None } diff --git a/vm/src/builtins/mappingproxy.rs b/vm/src/builtins/mappingproxy.rs index d886559af..0e054571f 100644 --- a/vm/src/builtins/mappingproxy.rs +++ b/vm/src/builtins/mappingproxy.rs @@ -67,7 +67,7 @@ impl PyMappingProxy { let key = PyStrRef::try_from_object(vm, key)?; class.attributes.read().get(key.as_str()).cloned() } - MappingProxyInner::Dict(obj) => obj.get_item(key, vm).ok(), + MappingProxyInner::Dict(obj) => obj.get_item(&*key, vm).ok(), }; Ok(opt) } diff --git a/vm/src/builtins/set.rs b/vm/src/builtins/set.rs index 9295e39ec..da5cd9d8c 100644 --- a/vm/src/builtins/set.rs +++ b/vm/src/builtins/set.rs @@ -174,7 +174,7 @@ impl PySetInner { ) -> PyResult { let set = self.copy(); for item in other.iter(vm)? { - set.content.delete_if_exists(vm, &item?)?; + set.content.delete_if_exists(vm, &*item?)?; } Ok(set) } @@ -231,13 +231,11 @@ impl PySetInner { } fn add(&self, item: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - self.content.insert(vm, item, ()) + self.content.insert(vm, &*item, ()) } fn remove(&self, item: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - self.retry_op_with_frozenset(&item, vm, |item, vm| { - self.content.delete(vm, item.to_owned()) - }) + self.retry_op_with_frozenset(&item, vm, |item, vm| self.content.delete(vm, item)) } fn discard(&self, item: &PyObject, vm: &VirtualMachine) -> PyResult { @@ -293,7 +291,7 @@ impl PySetInner { fn difference_update(&self, others: PosArgs, vm: &VirtualMachine) -> PyResult<()> { for iterable in others { for item in iterable.iter(vm)? { - self.content.delete_if_exists(vm, &item?)?; + self.content.delete_if_exists(vm, &*item?)?; } } Ok(()) diff --git a/vm/src/builtins/str.rs b/vm/src/builtins/str.rs index dad5a16e9..11b84e7f8 100644 --- a/vm/src/builtins/str.rs +++ b/vm/src/builtins/str.rs @@ -1147,7 +1147,7 @@ impl PyStr { let mut translated = String::new(); for c in self.as_str().chars() { - match table.get_item((c as u32).to_pyobject(vm), vm) { + match table.get_item(&*(c as u32).to_pyobject(vm), vm) { Ok(value) => { if let Some(text) = value.payload::() { translated.push_str(text.as_str()); @@ -1188,14 +1188,14 @@ impl PyStr { if to_str.len() == from_str.len() { for (c1, c2) in from_str.as_str().chars().zip(to_str.as_str().chars()) { new_dict.set_item( - vm.new_pyobj(c1 as u32), + &*vm.new_pyobj(c1 as u32), vm.new_pyobj(c2 as u32), vm, )?; } if let OptionalArg::Present(none_str) = none_str { for c in none_str.as_str().chars() { - new_dict.set_item(vm.new_pyobj(c as u32), vm.ctx.none(), vm)?; + new_dict.set_item(&*vm.new_pyobj(c as u32), vm.ctx.none(), vm)?; } } Ok(new_dict.to_pyobject(vm)) @@ -1215,12 +1215,17 @@ impl PyStr { match dict_or_str.downcast::() { Ok(dict) => { for (key, val) in dict { + // FIXME: ints are key-compatible if let Some(num) = key.payload::() { - new_dict.set_item(num.as_bigint().to_i32().to_pyobject(vm), val, vm)?; + new_dict.set_item( + &*num.as_bigint().to_i32().to_pyobject(vm), + val, + vm, + )?; } else if let Some(string) = key.payload::() { if string.len() == 1 { let num_value = string.as_str().chars().next().unwrap() as u32; - new_dict.set_item(num_value.to_pyobject(vm), val, vm)?; + new_dict.set_item(&*num_value.to_pyobject(vm), val, vm)?; } else { return Err(vm.new_value_error( "string keys in translate table must be of length 1".to_owned(), diff --git a/vm/src/dictdatatype.rs b/vm/src/dictdatatype.rs index 3e7dd1816..cd043827d 100644 --- a/vm/src/dictdatatype.rs +++ b/vm/src/dictdatatype.rs @@ -252,13 +252,13 @@ impl Dict { } /// Store a key - pub fn insert(&self, vm: &VirtualMachine, key: K, value: T) -> PyResult<()> + pub fn insert(&self, vm: &VirtualMachine, key: &K, value: T) -> PyResult<()> where - K: DictKey + ToPyObject, + K: DictKey + ?Sized, { let hash = key.key_hash(vm)?; let _removed = loop { - let (entry_index, index_index) = self.lookup(vm, &key, hash, None)?; + let (entry_index, index_index) = self.lookup(vm, key, hash, None)?; let mut inner = self.write(); if let IndexEntry::Index(index) = entry_index { // Update existing key @@ -285,19 +285,19 @@ impl Dict { Ok(()) } - pub fn contains(&self, vm: &VirtualMachine, key: &K) -> PyResult { + pub fn contains(&self, vm: &VirtualMachine, key: &K) -> PyResult { let (entry, _) = self.lookup(vm, key, key.key_hash(vm)?, None)?; Ok(matches!(entry, IndexEntry::Index(_))) } /// Retrieve a key #[cfg_attr(feature = "flame-it", flame("Dict"))] - pub fn get(&self, vm: &VirtualMachine, key: &K) -> PyResult> { + pub fn get(&self, vm: &VirtualMachine, key: &K) -> PyResult> { let hash = key.key_hash(vm)?; self._get_inner(vm, key, hash) } - fn _get_inner( + fn _get_inner( &self, vm: &VirtualMachine, key: &K, @@ -325,7 +325,7 @@ impl Dict { Ok(ret) } - pub fn get_chain( + pub fn get_chain( &self, other: &Self, vm: &VirtualMachine, @@ -353,11 +353,11 @@ impl Dict { } /// Delete a key - pub fn delete(&self, vm: &VirtualMachine, key: K) -> PyResult<()> + pub fn delete(&self, vm: &VirtualMachine, key: &K) -> PyResult<()> where - K: DictKey + ToPyObject, + K: DictKey + ?Sized, { - if self.delete_if_exists(vm, &key)? { + if self.delete_if_exists(vm, key)? { Ok(()) } else { Err(vm.new_key_error(key.to_pyobject(vm))) @@ -366,7 +366,7 @@ impl Dict { pub fn delete_if_exists(&self, vm: &VirtualMachine, key: &K) -> PyResult where - K: DictKey, + K: DictKey + ?Sized, { self.delete_if(vm, key, |_| Ok(true)) } @@ -375,7 +375,7 @@ impl Dict { /// the dict's internal mutex is held pub(crate) fn delete_if(&self, vm: &VirtualMachine, key: &K, pred: F) -> PyResult where - K: DictKey, + K: DictKey + ?Sized, F: Fn(&T) -> PyResult, { let hash = key.key_hash(vm)?; @@ -408,14 +408,14 @@ impl Dict { Ok(()) } - pub fn setdefault(&self, vm: &VirtualMachine, key: K, default: F) -> PyResult + pub fn setdefault(&self, vm: &VirtualMachine, key: &K, default: F) -> PyResult where - K: DictKey + ToPyObject, + K: DictKey + ?Sized, F: FnOnce() -> T, { let hash = key.key_hash(vm)?; let res = loop { - let lookup = self.lookup(vm, &key, hash, None)?; + let lookup = self.lookup(vm, key, hash, None)?; let (entry, index_index) = lookup; if let IndexEntry::Index(index) = entry { let inner = self.read(); @@ -444,16 +444,16 @@ impl Dict { pub fn setdefault_entry( &self, vm: &VirtualMachine, - key: K, + key: &K, default: F, ) -> PyResult<(PyObjectRef, T)> where - K: DictKey + ToPyObject, + K: DictKey + ?Sized, F: FnOnce() -> T, { let hash = key.key_hash(vm)?; let res = loop { - let lookup = self.lookup(vm, &key, hash, None)?; + let lookup = self.lookup(vm, key, hash, None)?; let (entry, index_index) = lookup; if let IndexEntry::Index(index) = entry { let inner = self.read(); @@ -533,7 +533,7 @@ impl Dict { /// Lookup the index for the given key. #[cfg_attr(feature = "flame-it", flame("Dict"))] - fn lookup( + fn lookup( &self, vm: &VirtualMachine, key: &K, @@ -630,7 +630,7 @@ impl Dict { } /// Retrieve and delete a key - pub fn pop(&self, vm: &VirtualMachine, key: &K) -> PyResult> { + pub fn pop(&self, vm: &VirtualMachine, key: &K) -> PyResult> { let hash_value = key.key_hash(vm)?; let removed = loop { let lookup = self.lookup(vm, key, hash_value, None)?; @@ -671,6 +671,11 @@ type LookupResult = (IndexEntry, IndexIndex); /// - PyObjectRef -> arbitrary python type used as key /// - str -> string reference used as key, this is often used internally pub trait DictKey { + type Owned: ToPyObject; + fn _to_owned(&self, vm: &VirtualMachine) -> Self::Owned; + fn to_pyobject(&self, vm: &VirtualMachine) -> PyObjectRef { + self._to_owned(vm).to_pyobject(vm) + } fn key_hash(&self, vm: &VirtualMachine) -> PyResult; fn key_is(&self, other: &PyObject) -> bool; fn key_eq(&self, vm: &VirtualMachine, other_key: &PyObject) -> PyResult; @@ -679,45 +684,13 @@ pub trait DictKey { /// Implement trait for PyObjectRef such that we can use python objects /// to index dictionaries. -impl DictKey for PyObjectRef { - #[inline] - fn key_hash(&self, vm: &VirtualMachine) -> PyResult { - (**self).key_hash(vm) - } - #[inline] - fn key_is(&self, other: &PyObject) -> bool { - (**self).key_is(other) - } - #[inline] - fn key_eq(&self, vm: &VirtualMachine, other_key: &PyObject) -> PyResult { - (**self).key_eq(vm, other_key) - } - #[inline] - fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult { - (**self).key_as_isize(vm) - } -} - -impl DictKey for &PyObject { - #[inline] - fn key_hash(&self, vm: &VirtualMachine) -> PyResult { - (**self).key_hash(vm) - } - #[inline] - fn key_is(&self, other: &PyObject) -> bool { - (**self).key_is(other) - } - #[inline] - fn key_eq(&self, vm: &VirtualMachine, other_key: &PyObject) -> PyResult { - (**self).key_eq(vm, other_key) - } - #[inline] - fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult { - (**self).key_as_isize(vm) - } -} - impl DictKey for PyObject { + type Owned = PyObjectRef; + #[inline] + fn _to_owned(&self, _vm: &VirtualMachine) -> Self::Owned { + self.to_owned() + } + fn key_hash(&self, vm: &VirtualMachine) -> PyResult { self.hash(vm) } @@ -736,6 +709,12 @@ impl DictKey for PyObject { } impl DictKey for Py { + type Owned = PyStrRef; + #[inline] + fn _to_owned(&self, _vm: &VirtualMachine) -> Self::Owned { + self.to_owned() + } + fn key_hash(&self, vm: &VirtualMachine) -> PyResult { Ok(self.hash(vm)) } @@ -760,6 +739,12 @@ impl DictKey for Py { } impl DictKey for PyStrRef { + type Owned = Self; + #[inline] + fn _to_owned(&self, _vm: &VirtualMachine) -> Self::Owned { + self.clone() + } + fn key_hash(&self, vm: &VirtualMachine) -> PyResult { Ok(self.hash(vm)) } @@ -784,6 +769,12 @@ impl DictKey for PyStrRef { } impl DictKey for PyRefExact { + type Owned = Self; + #[inline] + fn _to_owned(&self, _vm: &VirtualMachine) -> Self::Owned { + self.clone() + } + fn key_hash(&self, vm: &VirtualMachine) -> PyResult { (**self).key_hash(vm) } @@ -803,6 +794,12 @@ impl DictKey for PyRefExact { /// Implement trait for the str type, so that we can use strings /// to index dictionaries. impl DictKey for &str { + type Owned = String; + #[inline] + fn _to_owned(&self, _vm: &VirtualMachine) -> Self::Owned { + (**self).to_owned() + } + fn key_hash(&self, vm: &VirtualMachine) -> PyResult { // follow a similar route as the hashing of PyStrRef Ok(vm.state.hash_secret.hash_str(*self)) @@ -829,7 +826,46 @@ impl DictKey for &str { } } +impl DictKey for str { + type Owned = String; + #[inline] + fn _to_owned(&self, _vm: &VirtualMachine) -> Self::Owned { + self.to_owned() + } + + fn key_hash(&self, vm: &VirtualMachine) -> PyResult { + // follow a similar route as the hashing of PyStrRef + Ok(vm.state.hash_secret.hash_str(self)) + } + + fn key_is(&self, _other: &PyObject) -> bool { + // No matter who the other pyobject is, we are never the same thing, since + // we are a str, not a pyobject. + false + } + + fn key_eq(&self, vm: &VirtualMachine, other_key: &PyObject) -> PyResult { + if let Some(pystr) = str_exact(other_key, vm) { + Ok(pystr.as_str() == self) + } else { + // Fall back to PyObjectRef implementation. + let s = vm.ctx.new_str(self); + s.key_eq(vm, other_key) + } + } + + fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult { + Err(vm.new_type_error("'str' object cannot be interpreted as an integer".to_owned())) + } +} + impl DictKey for String { + type Owned = String; + #[inline] + fn _to_owned(&self, _vm: &VirtualMachine) -> Self::Owned { + self.clone() + } + fn key_hash(&self, vm: &VirtualMachine) -> PyResult { self.as_str().key_hash(vm) } @@ -848,6 +884,12 @@ impl DictKey for String { } impl DictKey for usize { + type Owned = usize; + #[inline] + fn _to_owned(&self, _vm: &VirtualMachine) -> Self::Owned { + *self + } + fn key_hash(&self, vm: &VirtualMachine) -> PyResult { Ok(vm.state.hash_secret.hash_value(self)) } @@ -902,25 +944,25 @@ mod tests { let key1 = vm.new_pyobj(true); let value1 = vm.new_pyobj(ascii!("abc")); - dict.insert(&vm, key1.clone(), value1.clone()).unwrap(); + dict.insert(&vm, &*key1, value1.clone()).unwrap(); assert_eq!(1, dict.len()); let key2 = vm.new_pyobj(ascii!("x")); let value2 = vm.new_pyobj(ascii!("def")); - dict.insert(&vm, key2.clone(), value2.clone()).unwrap(); + dict.insert(&vm, &*key2, value2.clone()).unwrap(); assert_eq!(2, dict.len()); - dict.insert(&vm, key1.clone(), value2.clone()).unwrap(); + dict.insert(&vm, &*key1, value2.clone()).unwrap(); assert_eq!(2, dict.len()); - dict.delete(&vm, key1.clone()).unwrap(); + dict.delete(&vm, &*key1).unwrap(); assert_eq!(1, dict.len()); - dict.insert(&vm, key1.clone(), value2.clone()).unwrap(); + dict.insert(&vm, &*key1, value2.clone()).unwrap(); assert_eq!(2, dict.len()); - assert_eq!(true, dict.contains(&vm, &key1).unwrap()); - assert_eq!(true, dict.contains(&vm, &"x").unwrap()); + assert_eq!(true, dict.contains(&vm, &*key1).unwrap()); + assert_eq!(true, dict.contains(&vm, "x").unwrap()); let val = dict.get(&vm, &"x").unwrap().unwrap(); vm.bool_eq(&val, &value2) diff --git a/vm/src/format.rs b/vm/src/format.rs index 954ea5763..3ce39d724 100644 --- a/vm/src/format.rs +++ b/vm/src/format.rs @@ -812,10 +812,10 @@ impl FormatString { argument = argument.get_attr(attribute.as_str(), vm)?; } FieldNamePart::Index(index) => { - argument = argument.get_item(index, vm)?; + argument = argument.get_item(&index, vm)?; } FieldNamePart::StringIndex(index) => { - argument = argument.get_item(index, vm)?; + argument = argument.get_item(&index, vm)?; } } } @@ -877,7 +877,7 @@ impl FormatString { FieldType::Auto | FieldType::Index(_) => { Err(vm.new_value_error("Format string contains positional fields".to_owned())) } - FieldType::Keyword(keyword) => dict.get_item(keyword, vm), + FieldType::Keyword(keyword) => dict.get_item(&keyword, vm), }) } } diff --git a/vm/src/frame.rs b/vm/src/frame.rs index f471879c9..a35a5e587 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -17,7 +17,7 @@ use crate::{ scope::Scope, stdlib::builtins, vm::PyMethod, - AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine, + AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine, }; use indexmap::IndexMap; use itertools::Itertools; @@ -543,7 +543,7 @@ impl ExecutingFrame<'_> { bytecode::Instruction::StoreGlobal(idx) => { let value = self.pop_value(); self.globals - .set_item(self.code.names[*idx as usize].clone(), value, vm)?; + .set_item(&*self.code.names[*idx as usize].clone(), value, vm)?; Ok(None) } bytecode::Instruction::StoreDeref(i) => { @@ -572,7 +572,7 @@ impl ExecutingFrame<'_> { } bytecode::Instruction::DeleteGlobal(idx) => { let name = &self.code.names[*idx as usize]; - match self.globals.del_item(name.clone(), vm) { + match self.globals.del_item(&*name, vm) { Ok(()) => {} Err(e) if e.fast_isinstance(&vm.ctx.exceptions.key_error) => { return Err( @@ -695,7 +695,7 @@ impl ExecutingFrame<'_> { }; let key = self.pop_value(); let value = self.pop_value(); - dict.set_item(key, value, vm)?; + dict.set_item(&*key, value, vm)?; Ok(None) } bytecode::Instruction::MapAddRev { i } => { @@ -707,7 +707,7 @@ impl ExecutingFrame<'_> { }; let value = self.pop_value(); let key = self.pop_value(); - dict.set_item(key, value, vm)?; + dict.set_item(&*key, value, vm)?; Ok(None) } bytecode::Instruction::BinaryOperation { op } => self.execute_binop(vm, *op), @@ -1097,10 +1097,12 @@ impl ExecutingFrame<'_> { } #[inline] - fn load_global_or_builtin(&self, name: &PyStrRef, vm: &VirtualMachine) -> PyResult { + fn load_global_or_builtin(&self, name: &Py, vm: &VirtualMachine) -> PyResult { self.globals - .get_chain(self.builtins, name.clone(), vm)? - .ok_or_else(|| vm.new_name_error(format!("name '{}' is not defined", name), name)) + .get_chain(self.builtins, name, vm)? + .ok_or_else(|| { + vm.new_name_error(format!("name '{}' is not defined", name), &name.to_owned()) + }) } #[cfg_attr(feature = "flame-it", flame("Frame"))] @@ -1153,7 +1155,7 @@ impl ExecutingFrame<'_> { .clone() .get_attr("modules", vm) .map_err(|_| err())?; - sys_modules.get_item(full_mod_name, vm).map_err(|_| err()) + sys_modules.get_item(&full_mod_name, vm).map_err(|_| err()) } #[cfg_attr(feature = "flame-it", flame("Frame"))] @@ -1260,7 +1262,7 @@ impl ExecutingFrame<'_> { fn execute_subscript(&mut self, vm: &VirtualMachine) -> FrameResult { let b_ref = self.pop_value(); let a_ref = self.pop_value(); - let value = a_ref.get_item(b_ref, vm)?; + let value = a_ref.get_item(&*b_ref, vm)?; self.push_value(value); Ok(None) } @@ -1269,14 +1271,14 @@ impl ExecutingFrame<'_> { let idx = self.pop_value(); let obj = self.pop_value(); let value = self.pop_value(); - obj.set_item(idx, value, vm)?; + obj.set_item(&*idx, value, vm)?; Ok(None) } fn execute_delete_subscript(&mut self, vm: &VirtualMachine) -> FrameResult { let idx = self.pop_value(); let obj = self.pop_value(); - obj.del_item(idx, vm)?; + obj.del_item(&*idx, vm)?; Ok(None) } @@ -1298,7 +1300,7 @@ impl ExecutingFrame<'_> { for (key, value) in dict { #[allow(clippy::collapsible_if)] if for_call { - if map_obj.contains_key(key.clone(), vm) { + if map_obj.contains_key(&*key, vm) { let key_repr = &key.repr(vm)?; let msg = format!( "got multiple values for keyword argument {}", @@ -1307,12 +1309,12 @@ impl ExecutingFrame<'_> { return Err(vm.new_type_error(msg)); } } - map_obj.set_item(key, value, vm)?; + map_obj.set_item(&*key, value, vm)?; } } } else { for (key, value) in self.pop_multiple(2 * size).tuples() { - map_obj.set_item(key, value, vm)?; + map_obj.set_item(&*key, value, vm)?; } } diff --git a/vm/src/intern.rs b/vm/src/intern.rs index 011643ccd..8d583fa97 100644 --- a/vm/src/intern.rs +++ b/vm/src/intern.rs @@ -1,7 +1,6 @@ use crate::{ builtins::{PyStr, PyTypeRef}, common::lock::PyRwLock, - convert::ToPyObject, PyRef, PyRefExact, }; use std::ops::Deref; @@ -89,7 +88,7 @@ mod sealed { } /// A sealed marker trait for `DictKey` types that always become an exact instance of `str` -pub trait Internable: sealed::SealedInternable + crate::dictdatatype::DictKey + ToPyObject { +pub trait Internable: sealed::SealedInternable + crate::dictdatatype::DictKey { fn as_str(&self) -> &str; fn into_pyref(self, str_type: PyTypeRef) -> PyRefExact; } diff --git a/vm/src/protocol/object.rs b/vm/src/protocol/object.rs index 048d51132..f92cbedff 100644 --- a/vm/src/protocol/object.rs +++ b/vm/src/protocol/object.rs @@ -133,7 +133,7 @@ impl PyObject { #[cfg_attr(feature = "flame-it", flame)] pub fn generic_setattr( &self, - attr_name: PyStrRef, + attr_name: PyStrRef, // TODO: Py value: Option, vm: &VirtualMachine, ) -> PyResult<()> { @@ -148,9 +148,9 @@ impl PyObject { if let Some(dict) = self.dict() { if let Some(value) = value { - dict.set_item(attr_name, value, vm)?; + dict.set_item(&*attr_name, value, vm)?; } else { - dict.del_item(attr_name.clone(), vm).map_err(|e| { + dict.del_item(&*attr_name, vm).map_err(|e| { if e.fast_isinstance(&vm.ctx.exceptions.key_error) { vm.new_attribute_error(format!( "'{}' object has no attribute '{}'", @@ -197,8 +197,7 @@ impl PyObject { { drop(descr_cls); let cls = obj_cls.into_owned().into(); - return descr_get(descr, Some(self.to_pyobject(vm)), Some(cls), vm) - .map(Some); + return descr_get(descr, Some(self.to_owned()), Some(cls), vm).map(Some); } } drop(descr_cls); @@ -221,14 +220,13 @@ impl PyObject { match descr_get { Some(descr_get) => { let cls = obj_cls.into_owned().into(); - descr_get(attr, Some(self.to_pyobject(vm)), Some(cls), vm).map(Some) + descr_get(attr, Some(self.to_owned()), Some(cls), vm).map(Some) } None => Ok(Some(attr)), } } else if let Some(getter) = obj_cls.get_attr("__getattr__") { drop(obj_cls); - vm.invoke(&getter, (self.to_pyobject(vm), name_str)) - .map(Some) + vm.invoke(&getter, (self.to_owned(), name_str)).map(Some) } else { Ok(None) } @@ -515,11 +513,7 @@ impl PyObject { .ok_or_else(|| vm.new_type_error(format!("object of type '{}' has no len()", &self)))? } - pub fn get_item( - &self, - needle: K, - vm: &VirtualMachine, - ) -> PyResult { + pub fn get_item(&self, needle: &K, vm: &VirtualMachine) -> PyResult { if let Some(dict) = self.downcast_ref_if_exact::(vm) { return dict.get_item(needle, vm); } @@ -547,9 +541,9 @@ impl PyObject { } } - pub fn set_item( + pub fn set_item( &self, - needle: K, + needle: &K, value: PyObjectRef, vm: &VirtualMachine, ) -> PyResult<()> { @@ -574,11 +568,7 @@ impl PyObject { } } - pub fn del_item( - &self, - needle: K, - vm: &VirtualMachine, - ) -> PyResult<()> { + pub fn del_item(&self, needle: &K, vm: &VirtualMachine) -> PyResult<()> { if let Some(dict) = self.downcast_ref_if_exact::(vm) { return dict.del_item(needle, vm); } diff --git a/vm/src/py_serde.rs b/vm/src/py_serde.rs index d8797d1e0..7491c0064 100644 --- a/vm/src/py_serde.rs +++ b/vm/src/py_serde.rs @@ -205,7 +205,7 @@ impl<'de> Visitor<'de> for PyObjectDeserializer<'de> { // Although JSON keys must be strings, implementation accepts any keys // and can be reused by other deserializers without such limit while let Some((key_obj, value)) = access.next_entry_seed(self.clone(), self.clone())? { - dict.set_item(key_obj, value, self.vm).unwrap(); + dict.set_item(&*key_obj, value, self.vm).unwrap(); } Ok(dict.into()) } diff --git a/vm/src/stdlib/errno.rs b/vm/src/stdlib/errno.rs index ac0e4eea3..c1a487c34 100644 --- a/vm/src/stdlib/errno.rs +++ b/vm/src/stdlib/errno.rs @@ -13,9 +13,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { for (name, code) in ERROR_CODES { let name = vm.ctx.new_str(*name); let code = vm.new_pyobj(*code); - errorcode - .set_item(code.clone(), name.clone().into(), vm) - .unwrap(); + errorcode.set_item(&*code, name.clone().into(), vm).unwrap(); module.set_attr(name, code, vm).unwrap(); } module diff --git a/vm/src/stdlib/imp.rs b/vm/src/stdlib/imp.rs index 5111140fa..ab18738ff 100644 --- a/vm/src/stdlib/imp.rs +++ b/vm/src/stdlib/imp.rs @@ -76,7 +76,7 @@ mod _imp { let name = spec.get_attr("name", vm)?; let name = PyStrRef::try_from_object(vm, name)?; - if let Ok(module) = sys_modules.get_item(name.clone(), vm) { + if let Ok(module) = sys_modules.get_item(&*name, vm) { Ok(module) } else if let Some(make_module_func) = vm.state.module_inits.get(name.as_str()) { Ok(make_module_func(vm)) diff --git a/vm/src/stdlib/marshal.rs b/vm/src/stdlib/marshal.rs index 707a46505..81d5bbeeb 100644 --- a/vm/src/stdlib/marshal.rs +++ b/vm/src/stdlib/marshal.rs @@ -201,11 +201,7 @@ mod decl { )), }); // Marshalled tuples are always in format key:value. - dict.insert( - vm, - items.get(0).unwrap().clone(), - items.get(1).unwrap().clone(), - )?; + dict.insert(vm, &**items.get(0).unwrap(), items.get(1).unwrap().clone())?; } Ok(PyDict::from_entries(dict)) } diff --git a/vm/src/stdlib/nt.rs b/vm/src/stdlib/nt.rs index d89dcca4f..178f3e8a4 100644 --- a/vm/src/stdlib/nt.rs +++ b/vm/src/stdlib/nt.rs @@ -80,9 +80,7 @@ pub(crate) mod module { let environ = vm.ctx.new_dict(); for (key, value) in env::vars() { - environ - .set_item(vm.new_pyobj(key), vm.new_pyobj(value), vm) - .unwrap(); + environ.set_item(&key, vm.new_pyobj(value), vm).unwrap(); } environ } diff --git a/vm/src/stdlib/operator.rs b/vm/src/stdlib/operator.rs index e13749cf1..ac72893c3 100644 --- a/vm/src/stdlib/operator.rs +++ b/vm/src/stdlib/operator.rs @@ -226,13 +226,13 @@ mod _operator { /// Remove the value of a at index b. #[pyfunction] fn delitem(a: PyObjectRef, b: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - a.del_item(b, vm) + a.del_item(&*b, vm) } /// Return the value of a at index b. #[pyfunction] fn getitem(a: PyObjectRef, b: PyObjectRef, vm: &VirtualMachine) -> PyResult { - a.get_item(b, vm) + a.get_item(&*b, vm) } /// Return the number of occurrences of b in a. @@ -255,7 +255,7 @@ mod _operator { c: PyObjectRef, vm: &VirtualMachine, ) -> PyResult<()> { - a.set_item(b, c, vm) + a.set_item(&*b, c, vm) } /// Return an estimate of the number of items in obj. @@ -565,12 +565,12 @@ mod _operator { fn call(zelf: &Py, obj: Self::Args, vm: &VirtualMachine) -> PyResult { // Handle case where we only have one attribute. if zelf.items.len() == 1 { - return obj.get_item(zelf.items[0].clone(), vm); + return obj.get_item(&*zelf.items[0], vm); } // Build tuple and call get_single on each element in attrs. let mut results = Vec::with_capacity(zelf.items.len()); for item in &zelf.items { - results.push(obj.get_item(item.clone(), vm)?); + results.push(obj.get_item(&**item, vm)?); } Ok(vm.ctx.new_tuple(results).into()) } diff --git a/vm/src/stdlib/posix.rs b/vm/src/stdlib/posix.rs index 717d10e8d..4b0dab941 100644 --- a/vm/src/stdlib/posix.rs +++ b/vm/src/stdlib/posix.rs @@ -291,7 +291,7 @@ pub mod module { for (key, value) in env::vars_os() { let key: PyObjectRef = vm.ctx.new_bytes(key.into_vec()).into(); let value: PyObjectRef = vm.ctx.new_bytes(value.into_vec()).into(); - environ.set_item(key, value, vm).unwrap(); + environ.set_item(&*key, value, vm).unwrap(); } environ diff --git a/vm/src/stdlib/posix_compat.rs b/vm/src/stdlib/posix_compat.rs index 487f359ff..c3a3bea7e 100644 --- a/vm/src/stdlib/posix_compat.rs +++ b/vm/src/stdlib/posix_compat.rs @@ -51,7 +51,7 @@ pub(crate) mod module { for (key, value) in env::vars_os() { let key: PyObjectRef = vm.ctx.new_bytes(key.into_vec()).into(); let value: PyObjectRef = vm.ctx.new_bytes(value.into_vec()).into(); - environ.set_item(key, value, vm).unwrap(); + environ.set_item(&*key, value, vm).unwrap(); } environ diff --git a/vm/src/stdlib/sre.rs b/vm/src/stdlib/sre.rs index 389257d60..9c0abd1c6 100644 --- a/vm/src/stdlib/sre.rs +++ b/vm/src/stdlib/sre.rs @@ -725,7 +725,7 @@ mod _sre { .and_then(|x| self.get_slice(x, str_drive, vm)) .map(|x| x.to_pyobject(vm)) .unwrap_or_else(|| default.clone()); - dict.set_item(key, value, vm)?; + dict.set_item(&*key, value, vm)?; } Ok(dict) }) @@ -750,7 +750,7 @@ mod _sre { } else { self.pattern .groupindex - .get_item_opt(group, vm) + .get_item_opt(&*group, vm) .ok()?? .downcast::() .ok()? diff --git a/vm/src/stdlib/thread.rs b/vm/src/stdlib/thread.rs index 4125abbac..999dccdc0 100644 --- a/vm/src/stdlib/thread.rs +++ b/vm/src/stdlib/thread.rs @@ -371,9 +371,9 @@ pub(crate) mod _thread { } else { let dict = zelf.ldict(vm); if let Some(value) = value { - dict.set_item(attr, value, vm)?; + dict.set_item(&attr, value, vm)?; } else { - dict.del_item(attr, vm)?; + dict.del_item(&attr, vm)?; } Ok(()) } diff --git a/vm/src/stdlib/weakref.rs b/vm/src/stdlib/weakref.rs index 1866e9abe..372c746e6 100644 --- a/vm/src/stdlib/weakref.rs +++ b/vm/src/stdlib/weakref.rs @@ -54,7 +54,7 @@ mod _weakref { vm: &VirtualMachine, ) -> PyResult<()> { dict._as_dict_inner() - .delete_if(vm, &key, |wr| { + .delete_if(vm, &*key, |wr| { let wr = wr .payload::() .ok_or_else(|| vm.new_type_error("not a weakref".to_owned()))?; diff --git a/vm/src/vm/method.rs b/vm/src/vm/method.rs index 1a0fc4415..de8e28747 100644 --- a/vm/src/vm/method.rs +++ b/vm/src/vm/method.rs @@ -56,7 +56,7 @@ impl PyMethod { }; if let Some(dict) = obj.dict() { - if let Some(attr) = dict.get_item_opt(name.clone(), vm)? { + if let Some(attr) = dict.get_item_opt(&*name, vm)? { return Ok(Self::Attribute(attr)); } } diff --git a/vm/src/vm/mod.rs b/vm/src/vm/mod.rs index 400e30d49..87e4ac22d 100644 --- a/vm/src/vm/mod.rs +++ b/vm/src/vm/mod.rs @@ -410,7 +410,7 @@ impl VirtualMachine { None } else { let sys_modules = self.sys_module.get_attr("modules", self)?; - sys_modules.get_item(module.clone(), self).ok() + sys_modules.get_item(&*module, self).ok() }; match cached_module { diff --git a/wasm/lib/src/vm_class.rs b/wasm/lib/src/vm_class.rs index 51ea69e2d..a82d44bd6 100644 --- a/wasm/lib/src/vm_class.rs +++ b/wasm/lib/src/vm_class.rs @@ -229,7 +229,7 @@ impl WASMVirtualMachine { pub fn add_to_scope(&self, name: String, value: JsValue) -> Result<(), JsValue> { self.with_vm(move |vm, StoredVirtualMachine { ref scope, .. }| { let value = convert::js_to_py(vm, value); - scope.globals.set_item(name, value, vm).into_js(vm) + scope.globals.set_item(&name, value, vm).into_js(vm) })? } @@ -296,7 +296,7 @@ impl WASMVirtualMachine { let module = vm.new_module(&name, attrs, None); let sys_modules = vm.sys_module.get_attr("modules", vm).into_js(vm)?; - sys_modules.set_item(name, module, vm).into_js(vm)?; + sys_modules.set_item(&name, module, vm).into_js(vm)?; Ok(()) })? @@ -315,7 +315,7 @@ impl WASMVirtualMachine { } let sys_modules = vm.sys_module.get_attr("modules", vm).into_js(vm)?; - sys_modules.set_item(name, py_module, vm).into_js(vm)?; + sys_modules.set_item(&name, py_module, vm).into_js(vm)?; Ok(()) })?