@@ -2,17 +2,48 @@ use std::marker::PhantomData;
2
2
use std:: ops:: Deref ;
3
3
4
4
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
+ } ;
6
9
use crate :: vm:: VirtualMachine ;
7
10
8
11
// TODO: Move PyFuncArgs, FromArgs, etc. here
9
12
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.
10
24
pub struct PyRef < T > {
11
25
// invariant: this obj must always have payload of type T
12
26
obj : PyObjectRef ,
13
27
_payload : PhantomData < T > ,
14
28
}
15
29
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
+
16
47
impl < T > Deref for PyRef < T >
17
48
where
18
49
T : PyObjectPayload2 ,
35
66
_payload : PhantomData ,
36
67
} )
37
68
} 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
+ ) ) )
39
75
}
40
76
}
41
77
}
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