@@ -31,15 +31,19 @@ macro_rules! impl_fn_addr {
3131}
3232impl_fn_addr ! ( ) ;
3333
34- #[ derive( Clone ) ]
35- pub ( crate ) struct FnState {
36- addr : usize ,
37- original : Rc < dyn Any > ,
38- current_cast : Option < Rc < dyn Any > > ,
34+ trait ErasedFn : Any {
35+ fn addr ( & self ) -> usize ;
36+ }
37+
38+ impl < T : FnAddr + Any > ErasedFn for T {
39+ fn addr ( & self ) -> usize {
40+ self . fn_addr ( )
41+ }
3942}
4043
4144pub struct FnPtr < T > {
42- state : Option < Rc < FnState > > ,
45+ original : Option < Rc < dyn ErasedFn > > ,
46+ current_cast : Option < Rc < dyn ErasedFn > > ,
4347 // FnPtr does not use T, hence wrap in PhantomData
4448 _marker : PhantomData < T > ,
4549}
@@ -48,54 +52,48 @@ impl<T> FnPtr<T> {
4852 #[ inline]
4953 pub fn null ( ) -> Self {
5054 FnPtr {
51- state : None ,
55+ original : None ,
56+ current_cast : None ,
5257 _marker : PhantomData ,
5358 }
5459 }
5560
5661 #[ inline]
5762 pub fn is_null ( & self ) -> bool {
58- self . state . is_none ( )
63+ self . original . is_none ( )
5964 }
6065}
6166
6267impl < T : FnAddr + ' static > FnPtr < T > {
6368 pub fn new ( f : T ) -> Self {
64- let addr = f. fn_addr ( ) ;
65- let rc: Rc < dyn Any > = Rc :: new ( f) ;
69+ let rc: Rc < dyn ErasedFn > = Rc :: new ( f) ;
6670 FnPtr {
67- state : Some ( Rc :: new ( FnState {
68- addr,
69- original : rc. clone ( ) ,
70- current_cast : Some ( rc) ,
71- } ) ) ,
71+ original : Some ( rc. clone ( ) ) ,
72+ current_cast : Some ( rc) ,
7273 _marker : PhantomData ,
7374 }
7475 }
7576}
7677
7778impl < T : ' static > FnPtr < T > {
78- pub fn cast < U : ' static > ( & self , adapter : Option < U > ) -> FnPtr < U > {
79- let state = self . state . as_ref ( ) . expect ( "ub: null fn pointer cast" ) ;
79+ pub fn cast < U : FnAddr + ' static > ( & self , adapter : Option < U > ) -> FnPtr < U > {
80+ let original = self . original . as_ref ( ) . expect ( "ub: null fn pointer cast" ) ;
8081
81- let current_cast = if state
82+ let current_cast = if self
8283 . current_cast
8384 . as_ref ( )
84- . is_some_and ( |rc| ( * * rc) . type_id ( ) == TypeId :: of :: < U > ( ) )
85+ . is_some_and ( |rc| Any :: type_id ( & * * rc) == TypeId :: of :: < U > ( ) )
8586 {
86- state . current_cast . clone ( )
87- } else if ( * state . original ) . type_id ( ) == TypeId :: of :: < U > ( ) {
88- Some ( state . original . clone ( ) )
87+ self . current_cast . clone ( )
88+ } else if Any :: type_id ( & * * original) == TypeId :: of :: < U > ( ) {
89+ Some ( original. clone ( ) )
8990 } else {
90- adapter. map ( |a| Rc :: new ( a) as Rc < dyn Any > )
91+ adapter. map ( |a| Rc :: new ( a) as Rc < dyn ErasedFn > )
9192 } ;
9293
9394 FnPtr {
94- state : Some ( Rc :: new ( FnState {
95- addr : state. addr ,
96- original : state. original . clone ( ) ,
97- current_cast,
98- } ) ) ,
95+ original : Some ( original. clone ( ) ) ,
96+ current_cast,
9997 _marker : PhantomData ,
10098 }
10199 }
@@ -104,20 +102,24 @@ impl<T: 'static> FnPtr<T> {
104102impl < T : ' static > Deref for FnPtr < T > {
105103 type Target = T ;
106104 fn deref ( & self ) -> & T {
107- let state = self . state . as_ref ( ) . expect ( "ub: null fn pointer call" ) ;
108- match & state. current_cast {
109- Some ( rc) => rc
110- . downcast_ref :: < T > ( )
111- . expect ( "ub: fn pointer type mismatch" ) ,
112- None => panic ! ( "ub: calling through incompatible fn pointer type" ) ,
105+ if self . original . is_none ( ) {
106+ panic ! ( "ub: null fn pointer call" ) ;
113107 }
108+ let rc = self
109+ . current_cast
110+ . as_ref ( )
111+ . expect ( "ub: calling through incompatible fn pointer type" ) ;
112+ let any: & dyn Any = & * * rc;
113+ any. downcast_ref :: < T > ( )
114+ . expect ( "ub: fn pointer type mismatch" )
114115 }
115116}
116117
117118impl < T > Clone for FnPtr < T > {
118119 fn clone ( & self ) -> Self {
119120 FnPtr {
120- state : self . state . clone ( ) ,
121+ original : self . original . clone ( ) ,
122+ current_cast : self . current_cast . clone ( ) ,
121123 _marker : PhantomData ,
122124 }
123125 }
@@ -131,9 +133,9 @@ impl<T> Default for FnPtr<T> {
131133
132134impl < T > PartialEq for FnPtr < T > {
133135 fn eq ( & self , other : & Self ) -> bool {
134- match ( & self . state , & other. state ) {
136+ match ( & self . original , & other. original ) {
135137 ( None , None ) => true ,
136- ( Some ( a) , Some ( b) ) => a. addr == b. addr ,
138+ ( Some ( a) , Some ( b) ) => a. addr ( ) == b. addr ( ) ,
137139 _ => false ,
138140 }
139141 }
0 commit comments