@@ -2,17 +2,48 @@ use std::marker::PhantomData;
22use std:: ops:: Deref ;
33
44use 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+ } ;
69use 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.
1024pub struct PyRef < T > {
1125// invariant: this obj must always have payload of type T
1226obj : 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+
1647impl < T > Deref for PyRef < T >
1748where
1849T : PyObjectPayload2 ,
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+ }