Skip to content

Commit 839f906

Browse files
authored
Merge pull request RustPython#592 from RustPython/joey/improved-arg-errors
Improve error messages and add docs for new native function machinery
2 parents 4ce0a7c + 4e822ed commit 839f906

File tree

2 files changed

+222
-16
lines changed

2 files changed

+222
-16
lines changed

vm/src/function.rs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,48 @@ use std::marker::PhantomData;
22
use std::ops::Deref;
33

44
use crate::obj::objtype;
5-
use crate::pyobject::{PyObjectPayload2, PyObjectRef, PyResult, TryFromObject};
5+
use crate::pyobject::{
6+
IntoPyObject, PyContext, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult,
7+
TryFromObject, TypeProtocol,
8+
};
69
use crate::vm::VirtualMachine;
710

811
// TODO: Move PyFuncArgs, FromArgs, etc. here
912

13+
// TODO: `PyRef` probably actually belongs in the pyobject module.
14+
15+
/// A reference to the payload of a built-in object.
16+
///
17+
/// Note that a `PyRef<T>` can only deref to a shared / immutable reference.
18+
/// It is the payload type's responsibility to handle (possibly concurrent)
19+
/// mutability with locks or concurrent data structures if required.
20+
///
21+
/// A `PyRef<T>` can be directly returned from a built-in function to handle
22+
/// situations (such as when implementing in-place methods such as `__iadd__`)
23+
/// where a reference to the same object must be returned.
1024
pub struct PyRef<T> {
1125
// invariant: this obj must always have payload of type T
1226
obj: PyObjectRef,
1327
_payload: PhantomData<T>,
1428
}
1529

30+
impl<T> PyRef<T>
31+
where
32+
T: PyObjectPayload2,
33+
{
34+
pub fn new(ctx: &PyContext, payload: T) -> Self {
35+
PyRef {
36+
obj: PyObject::new(
37+
PyObjectPayload::AnyRustValue {
38+
value: Box::new(payload),
39+
},
40+
T::required_type(ctx),
41+
),
42+
_payload: PhantomData,
43+
}
44+
}
45+
}
46+
1647
impl<T> Deref for PyRef<T>
1748
where
1849
T: PyObjectPayload2,
@@ -35,7 +66,18 @@ where
3566
_payload: PhantomData,
3667
})
3768
} else {
38-
Err(vm.new_type_error("wrong type".to_string())) // TODO: better message
69+
let expected_type = vm.to_pystr(&T::required_type(&vm.ctx))?;
70+
let actual_type = vm.to_pystr(&obj.typ())?;
71+
Err(vm.new_type_error(format!(
72+
"Expected type {}, not {}",
73+
expected_type, actual_type,
74+
)))
3975
}
4076
}
4177
}
78+
79+
impl<T> IntoPyObject for PyRef<T> {
80+
fn into_pyobject(self, _ctx: &PyContext) -> PyResult {
81+
Ok(self.obj)
82+
}
83+
}

0 commit comments

Comments
 (0)