44// Support for FnPtr::cast synthesizing a call-through adapter automatically,
55// for any function pointer types T -> U.
66
7+ use std:: any:: Any ;
8+
79use crate :: rc:: Ptr ;
810use crate :: reinterpret:: ByteRepr ;
911use crate :: void:: { AnyPtr , ErasedPtr } ;
1012
1113// A type-erased view of one argument or return value, used only transiently
1214// (within a single adapted call) and never allocated.
13- pub ( crate ) enum ArgRepr < ' a > {
15+ pub enum ArgRepr < ' a > {
1416 Bytes ( [ u8 ; 16 ] , usize ) ,
1517 Ptr ( & ' a dyn ErasedPtr ) ,
18+ Record ( & ' a dyn Any ) ,
1619}
1720
18- pub ( crate ) trait FnPtrArg : ' static {
21+ pub trait FnPtrArg : ' static {
1922 fn to_repr ( & self ) -> ArgRepr < ' _ > ;
2023 // Panics if `r` describes a value that isn't a meaningful `Self` (wrong
2124 // kind, or same kind but incompatible size).
@@ -105,7 +108,9 @@ impl<T: ByteRepr> FnPtrArg for Ptr<T> {
105108 Some ( exact) => exact. clone ( ) ,
106109 None => e. as_bytes ( ) . reinterpret_cast ( ) ,
107110 } ,
108- ArgRepr :: Bytes ( ..) => panic ! ( "ub: calling through incompatible fn pointer type" ) ,
111+ ArgRepr :: Bytes ( ..) | ArgRepr :: Record ( _) => {
112+ panic ! ( "ub: calling through incompatible fn pointer type" )
113+ }
109114 }
110115 }
111116}
@@ -118,11 +123,23 @@ impl FnPtrArg for AnyPtr {
118123 fn from_repr ( r : & ArgRepr ) -> Self {
119124 match r {
120125 ArgRepr :: Ptr ( e) => e. as_bytes ( ) . to_any ( ) ,
121- ArgRepr :: Bytes ( ..) => panic ! ( "ub: calling through incompatible fn pointer type" ) ,
126+ ArgRepr :: Bytes ( ..) | ArgRepr :: Record ( _) => {
127+ panic ! ( "ub: calling through incompatible fn pointer type" )
128+ }
122129 }
123130 }
124131}
125132
133+ pub fn record_from_repr < T : Any + Clone > ( r : & ArgRepr ) -> T {
134+ match r {
135+ ArgRepr :: Record ( v) => v
136+ . downcast_ref :: < T > ( )
137+ . expect ( "ub: calling through incompatible fn pointer type" )
138+ . clone ( ) ,
139+ _ => panic ! ( "ub: calling through incompatible fn pointer type" ) ,
140+ }
141+ }
142+
126143// Fixed-capacity, type-erased view of a whole argument list: `FnPtrArgs`
127144// (below) converts a tuple of arguments to and from this common
128145// intermediate, so that converting between two argument lists never needs to
0 commit comments