Skip to content

Commit 5ac7fdc

Browse files
committed
Replace cast_history with original + current_cast
1 parent 83a7658 commit 5ac7fdc

1 file changed

Lines changed: 21 additions & 25 deletions

File tree

libcc2rs/src/fn_ptr.rs

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ impl_fn_addr!();
3434
#[derive(Clone)]
3535
pub(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

4041
pub struct FnPtr<T> {
@@ -60,10 +61,13 @@ impl<T> FnPtr<T> {
6061

6162
impl<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

Comments
 (0)