File tree Expand file tree Collapse file tree 1 file changed +13
-8
lines changed Expand file tree Collapse file tree 1 file changed +13
-8
lines changed Original file line number Diff line number Diff line change @@ -700,16 +700,23 @@ where
700
700
}
701
701
702
702
impl PyObject < dyn PyObjectPayload > {
703
- pub fn downcast < T : PyObjectPayload > ( self : Rc < Self > ) -> Option < PyRef < T > > {
703
+ /// Attempt to downcast this reference to a subclass.
704
+ ///
705
+ /// If the downcast fails, the original ref is returned in as `Err` so
706
+ /// another downcast can be attempted without unnecessary cloning.
707
+ ///
708
+ /// Note: The returned `Result` is _not_ a `PyResult`, even though the
709
+ /// types are compatible.
710
+ pub fn downcast < T : PyObjectPayload > ( self : Rc < Self > ) -> Result < PyRef < T > , PyObjectRef > {
704
711
if self . payload_is :: < T > ( ) {
705
- Some ( {
712
+ Ok ( {
706
713
PyRef {
707
714
obj : self ,
708
715
_payload : PhantomData ,
709
716
}
710
717
} )
711
718
} else {
712
- None
719
+ Err ( self )
713
720
}
714
721
}
715
722
}
@@ -1228,12 +1235,10 @@ where
1228
1235
B : PyValue ,
1229
1236
{
1230
1237
fn try_from_object ( vm : & VirtualMachine , obj : PyObjectRef ) -> PyResult < Self > {
1231
- // TODO: downcast could probably be reworked a bit to make these clones not necessary
1232
- obj. clone ( )
1233
- . downcast :: < A > ( )
1238
+ obj. downcast :: < A > ( )
1234
1239
. map ( Either2 :: A )
1235
- . or_else ( || obj. clone ( ) . downcast :: < B > ( ) . map ( Either2 :: B ) )
1236
- . ok_or_else ( | | {
1240
+ . or_else ( |obj | obj. clone ( ) . downcast :: < B > ( ) . map ( Either2 :: B ) )
1241
+ . map_err ( |obj | {
1237
1242
vm. new_type_error ( format ! (
1238
1243
"must be {} or {}, not {}" ,
1239
1244
A :: class( vm) ,
You can’t perform that action at this time.
0 commit comments