Skip to content

Commit edb8489

Browse files
committed
Make PyObject.dict an Option<RefCell<PyDictRef>>
1 parent 2124dd0 commit edb8489

File tree

7 files changed

+37
-22
lines changed

7 files changed

+37
-22
lines changed

Lib/_threading_local.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ def thread_deleted(_, idt=idt):
193193

194194
@contextmanager
195195
def _patch(self):
196+
old = object.__getattribute__(self, '__dict__')
196197
impl = object.__getattribute__(self, '_local__impl')
197198
try:
198199
dct = impl.get_dict()
@@ -203,6 +204,7 @@ def _patch(self):
203204
with impl.locallock:
204205
object.__setattr__(self, '__dict__', dct)
205206
yield
207+
object.__setattr__(self, '__dict__', old)
206208

207209

208210
class local:

vm/src/builtins.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,15 @@ fn make_scope(vm: &VirtualMachine, scope: ScopeArgs) -> PyResult<Scope> {
252252
let globals = match globals {
253253
Some(dict) => {
254254
if !dict.contains_key("__builtins__", vm) {
255-
let builtins_dict = vm.builtins.dict.as_ref().unwrap().as_object();
256-
dict.set_item("__builtins__", builtins_dict.clone(), vm)
257-
.unwrap();
255+
let builtins_dict = vm
256+
.builtins
257+
.dict
258+
.as_ref()
259+
.unwrap()
260+
.borrow()
261+
.as_object()
262+
.clone();
263+
dict.set_item("__builtins__", builtins_dict, vm).unwrap();
258264
}
259265
dict
260266
}

vm/src/frame.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ impl Frame {
699699

700700
// Grab all the names from the module and put them in the context
701701
if let Some(dict) = &module.dict {
702-
for (k, v) in dict {
702+
for (k, v) in &*dict.borrow() {
703703
let k = vm.to_str(&k)?;
704704
let k = k.as_str();
705705
if !k.starts_with('_') {

vm/src/obj/objmodule.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl PyModuleRef {
5050
let zelf = PyModule {}.into_ref_with_type(vm, cls)?;
5151
init_module_dict(
5252
vm,
53-
zelf.as_object().dict.as_ref().unwrap(),
53+
&zelf.as_object().dict.as_ref().unwrap().borrow(),
5454
name.into_object(),
5555
doc.flat_option()
5656
.map_or_else(|| vm.get_none(), PyRef::into_object),

vm/src/obj/objobject.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ fn object_setattr(
7777
}
7878

7979
if let Some(ref dict) = obj.clone().dict {
80-
dict.set_item(attr_name.as_str(), value, vm)?;
80+
dict.borrow().set_item(attr_name.as_str(), value, vm)?;
8181
Ok(())
8282
} else {
8383
Err(vm.new_attribute_error(format!(
@@ -98,7 +98,7 @@ fn object_delattr(obj: PyObjectRef, attr_name: PyStringRef, vm: &VirtualMachine)
9898
}
9999

100100
if let Some(ref dict) = obj.dict {
101-
dict.del_item(attr_name.as_str(), vm)?;
101+
dict.borrow().del_item(attr_name.as_str(), vm)?;
102102
Ok(())
103103
} else {
104104
Err(vm.new_attribute_error(format!(
@@ -130,7 +130,7 @@ pub fn object_dir(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyList> {
130130
if let Some(object_dict) = &obj.dict {
131131
vm.invoke(
132132
&vm.get_attribute(dict.clone().into_object(), "update")?,
133-
object_dict.clone().into_object(),
133+
object_dict.borrow().clone().into_object(),
134134
)?;
135135
}
136136

@@ -210,20 +210,22 @@ fn object_class_setter(
210210

211211
fn object_dict(object: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyDictRef> {
212212
if let Some(ref dict) = object.dict {
213-
Ok(dict.clone())
213+
Ok(dict.borrow().clone())
214214
} else {
215215
Err(vm.new_attribute_error("no dictionary.".to_string()))
216216
}
217217
}
218218

219-
fn object_dict_setter(
220-
_instance: PyObjectRef,
221-
_value: PyObjectRef,
222-
vm: &VirtualMachine,
223-
) -> PyResult {
224-
Err(vm.new_not_implemented_error(
225-
"Setting __dict__ attribute on an object isn't yet implemented".to_string(),
226-
))
219+
fn object_dict_setter(instance: PyObjectRef, value: PyDictRef, vm: &VirtualMachine) -> PyResult {
220+
if let Some(dict) = &instance.dict {
221+
*dict.borrow_mut() = value;
222+
Ok(vm.get_none())
223+
} else {
224+
Err(vm.new_attribute_error(format!(
225+
"'{}' object has no attribute '__dict__'",
226+
instance.class().name
227+
)))
228+
}
227229
}
228230

229231
fn object_getattribute(obj: PyObjectRef, name: PyStringRef, vm: &VirtualMachine) -> PyResult {

vm/src/pyobject.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::any::Any;
2-
use std::cell::Cell;
2+
use std::cell::{Cell, RefCell};
33
use std::collections::HashMap;
44
use std::fmt;
55
use std::marker::PhantomData;
@@ -522,7 +522,7 @@ impl PyContext {
522522
pub fn new_instance(&self, class: PyClassRef, dict: Option<PyDictRef>) -> PyObjectRef {
523523
PyObject {
524524
typ: class,
525-
dict,
525+
dict: dict.map(RefCell::new),
526526
payload: objobject::PyInstance,
527527
}
528528
.into_ref()
@@ -566,7 +566,7 @@ where
566566
T: ?Sized + PyObjectPayload,
567567
{
568568
pub typ: PyClassRef,
569-
pub dict: Option<PyDictRef>, // __dict__ member
569+
pub dict: Option<RefCell<PyDictRef>>, // __dict__ member
570570
pub payload: T,
571571
}
572572

@@ -1038,7 +1038,12 @@ where
10381038
{
10391039
#[allow(clippy::new_ret_no_self)]
10401040
pub fn new(payload: T, typ: PyClassRef, dict: Option<PyDictRef>) -> PyObjectRef {
1041-
PyObject { typ, dict, payload }.into_ref()
1041+
PyObject {
1042+
typ,
1043+
dict: dict.map(RefCell::new),
1044+
payload,
1045+
}
1046+
.into_ref()
10421047
}
10431048

10441049
// Move this object into a reference object, transferring ownership.

vm/src/vm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,7 @@ impl VirtualMachine {
952952
}
953953

954954
let attr = if let Some(ref dict) = obj.dict {
955-
dict.get_item_option(name_str.as_str(), self)?
955+
dict.borrow().get_item_option(name_str.as_str(), self)?
956956
} else {
957957
None
958958
};

0 commit comments

Comments
 (0)