@@ -34,7 +34,8 @@ impl_fn_addr!();
3434#[ derive( Clone ) ]
3535pub ( crate ) struct FnState {
3636 addr : usize ,
37- cast_history : Vec < Option < Rc < dyn Any > > > ,
37+ original : Rc < dyn Any > ,
38+ current_cast : Option < Rc < dyn Any > > ,
3839}
3940
4041pub struct FnPtr < T > {
@@ -60,10 +61,13 @@ impl<T> FnPtr<T> {
6061
6162impl < T : FnAddr + ' static > FnPtr < T > {
6263 pub fn new ( f : T ) -> Self {
64+ let addr = f. fn_addr ( ) ;
65+ let rc: Rc < dyn Any > = Rc :: new ( f) ;
6366 FnPtr {
6467 state : Some ( Rc :: new ( FnState {
65- addr : f. fn_addr ( ) ,
66- cast_history : vec ! [ Some ( Rc :: new( f) ) ] ,
68+ addr,
69+ original : rc. clone ( ) ,
70+ current_cast : Some ( rc) ,
6771 } ) ) ,
6872 _marker : PhantomData ,
6973 }
@@ -74,27 +78,23 @@ impl<T: 'static> FnPtr<T> {
7478 pub fn cast < U : ' static > ( & self , adapter : Option < U > ) -> FnPtr < U > {
7579 let state = self . state . as_ref ( ) . expect ( "ub: null fn pointer cast" ) ;
7680
77- for ( i, entry) in state. cast_history . iter ( ) . enumerate ( ) {
78- if let Some ( ref rc) = entry {
79- if ( * rc) . as_ref ( ) . type_id ( ) == TypeId :: of :: < U > ( ) {
80- return FnPtr {
81- state : Some ( Rc :: new ( FnState {
82- addr : state. addr ,
83- cast_history : state. cast_history [ ..=i] . to_vec ( ) ,
84- } ) ) ,
85- _marker : PhantomData ,
86- } ;
87- }
88- }
89- }
90-
91- let mut new_stack = state. cast_history . clone ( ) ;
92- new_stack. push ( adapter. map ( |a| Rc :: new ( a) as Rc < dyn Any > ) ) ;
81+ let current_cast = if state
82+ . current_cast
83+ . as_ref ( )
84+ . is_some_and ( |rc| ( * * rc) . type_id ( ) == TypeId :: of :: < U > ( ) )
85+ {
86+ state. current_cast . clone ( )
87+ } else if ( * state. original ) . type_id ( ) == TypeId :: of :: < U > ( ) {
88+ Some ( state. original . clone ( ) )
89+ } else {
90+ adapter. map ( |a| Rc :: new ( a) as Rc < dyn Any > )
91+ } ;
9392
9493 FnPtr {
9594 state : Some ( Rc :: new ( FnState {
9695 addr : state. addr ,
97- cast_history : new_stack,
96+ original : state. original . clone ( ) ,
97+ current_cast,
9898 } ) ) ,
9999 _marker : PhantomData ,
100100 }
@@ -105,11 +105,7 @@ impl<T: 'static> Deref for FnPtr<T> {
105105 type Target = T ;
106106 fn deref ( & self ) -> & T {
107107 let state = self . state . as_ref ( ) . expect ( "ub: null fn pointer call" ) ;
108- let entry = state
109- . cast_history
110- . last ( )
111- . expect ( "empty fn pointer cast_history" ) ;
112- match entry {
108+ match & state. current_cast {
113109 Some ( rc) => rc
114110 . downcast_ref :: < T > ( )
115111 . expect ( "ub: fn pointer type mismatch" ) ,
0 commit comments