@@ -60,6 +60,16 @@ impl<T: FnSig> Adapted for T {
6060 }
6161}
6262
63+ struct Closure < T : FnSig > ( Box < dyn Fn ( T :: Args ) -> T :: Ret > ) ;
64+
65+ impl < T : FnSig > Adapted for Closure < T > {
66+ fn call_adapted ( & self , args : ArgList < ' _ > , sink : & mut dyn FnMut ( ArgRepr < ' _ > ) ) {
67+ let converted_args = T :: Args :: from_list ( & args) ;
68+ let result = ( self . 0 ) ( converted_args) ;
69+ sink ( result. to_repr ( ) ) ;
70+ }
71+ }
72+
6373pub struct FnPtr < T : FnSig > {
6474 // Address of the function this pointer was created from. 0 for null,
6575 // which is never the address of a function.
@@ -71,7 +81,6 @@ pub struct FnPtr<T: FnSig> {
7181 // The function this pointer was created from, kept type-erased (but
7282 // still callable, through `Adapted`).
7383 original : Option < Rc < dyn Adapted > > ,
74- lambda : Option < Rc < dyn Fn ( T :: Args ) -> T :: Ret > > ,
7584}
7685
7786impl < T : FnSig > FnPtr < T > {
@@ -81,7 +90,6 @@ impl<T: FnSig> FnPtr<T> {
8190 addr : 0 ,
8291 current : None ,
8392 original : None ,
84- lambda : None ,
8593 }
8694 }
8795
@@ -96,7 +104,6 @@ impl<T: FnSig> FnPtr<T> {
96104 addr : f. fn_addr ( ) ,
97105 current : Some ( f) ,
98106 original : None ,
99- lambda : None ,
100107 }
101108 }
102109
@@ -107,13 +114,14 @@ impl<T: FnSig> FnPtr<T> {
107114 if self . is_null ( ) {
108115 panic ! ( "ub: null fn pointer call" ) ;
109116 }
110- if let Some ( lambda) = & self . lambda {
111- return lambda ( args) ;
112- }
113117 if let Some ( f) = self . current {
114118 return f. call_direct ( args) ;
115119 }
116120 if let Some ( original) = & self . original {
121+ let closure: & dyn Any = & * * original;
122+ if let Some ( closure) = closure. downcast_ref :: < Closure < T > > ( ) {
123+ return ( closure. 0 ) ( args) ;
124+ }
117125 let mut result = None ;
118126 original. call_adapted ( args. to_list ( ) , & mut |repr| {
119127 result = Some ( T :: Ret :: from_repr ( & repr) ) ;
@@ -152,17 +160,10 @@ impl<T: FnSig> FnPtr<T> {
152160 self . boxed_original ( )
153161 } ;
154162
155- let lambda: & dyn Any = & self . lambda ;
156- let lambda = lambda
157- . downcast_ref :: < Option < Rc < dyn Fn ( U :: Args ) -> U :: Ret > > > ( )
158- . cloned ( )
159- . flatten ( ) ;
160-
161163 FnPtr {
162164 addr : self . addr ,
163165 current : current_as_u. or ( original_as_u) ,
164166 original,
165- lambda,
166167 }
167168 }
168169
@@ -195,14 +196,13 @@ macro_rules! impl_fn_ptr_call {
195196 lambda: Lambda ,
196197 call: fn ( & Lambda $( , $a) * ) -> R ,
197198 ) -> Self {
198- let lambda = Rc :: new( lambda) ;
199+ let closure: Rc <dyn Adapted > = Rc :: new( Closure :: <fn ( $( $a, ) * ) -> R >(
200+ Box :: new( move |( $( $a, ) * ) : ( $( $a, ) * ) | call( & lambda $( , $a) * ) ) ,
201+ ) ) ;
199202 FnPtr {
200203 addr: call as usize ,
201204 current: None ,
202- original: None ,
203- lambda: Some ( Rc :: new( move |( $( $a, ) * ) : ( $( $a, ) * ) | {
204- call( & lambda $( , $a) * )
205- } ) ) ,
205+ original: Some ( closure) ,
206206 }
207207 }
208208
@@ -211,14 +211,16 @@ macro_rules! impl_fn_ptr_call {
211211 lambda: Lambda ,
212212 call: fn ( & mut Lambda $( , $a) * ) -> R ,
213213 ) -> Self {
214- let lambda = Rc :: new( UnsafeCell :: new( lambda) ) ;
214+ let lambda = UnsafeCell :: new( lambda) ;
215+ let closure: Rc <dyn Adapted > = Rc :: new( Closure :: <fn ( $( $a, ) * ) -> R >(
216+ Box :: new( move |( $( $a, ) * ) : ( $( $a, ) * ) | {
217+ call( unsafe { & mut * lambda. get( ) } $( , $a) * )
218+ } ) ,
219+ ) ) ;
215220 FnPtr {
216221 addr: call as usize ,
217222 current: None ,
218- original: None ,
219- lambda: Some ( Rc :: new( move |( $( $a, ) * ) : ( $( $a, ) * ) | {
220- call( unsafe { & mut * lambda. get( ) } $( , $a) * )
221- } ) ) ,
223+ original: Some ( closure) ,
222224 }
223225 }
224226 }
@@ -237,7 +239,6 @@ impl<T: FnSig> Clone for FnPtr<T> {
237239 addr : self . addr ,
238240 current : self . current ,
239241 original : self . original . clone ( ) ,
240- lambda : self . lambda . clone ( ) ,
241242 }
242243 }
243244}
0 commit comments