Skip to content

Commit f6ac637

Browse files
committed
Copy Any impl to avoid boxing
1 parent 0693913 commit f6ac637

File tree

1 file changed

+31
-17
lines changed

1 file changed

+31
-17
lines changed

script/src/script.rs

+31-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::bytecode::{ByteCode, CallResult, Environment, RunError};
2-
use core::any::Any;
2+
use core::any::{Any, TypeId};
33
use core::fmt::Debug;
44
use core::ops::{Add, Mul};
55
use rustc_hash::FxHashMap;
@@ -47,23 +47,46 @@ pub enum CallError {
4747
AlreadyBorrowed,
4848
}
4949

50-
pub trait ScriptType: Debug + Any {
50+
pub trait ScriptType: Debug + 'static {
5151
fn call(&self, function: &str, args: &[Rc<dyn ScriptType>]) -> CallResult<CallError>;
5252

5353
fn dup(&self) -> Rc<dyn ScriptType>;
5454

55+
#[inline]
5556
fn mul(&self, rhs: &Rc<dyn ScriptType>) -> CallResult<CallError> {
5657
let _ = rhs;
5758
Err(CallError::InvalidOperator)
5859
}
5960

61+
#[inline]
6062
fn add(&self, rhs: &Rc<dyn ScriptType>) -> CallResult<CallError> {
6163
let _ = rhs;
6264
Err(CallError::InvalidOperator)
6365
}
6466

65-
// rust pls
66-
fn as_any(&self) -> Box<dyn Any>;
67+
#[inline]
68+
fn type_id(&self) -> TypeId {
69+
Any::type_id(self)
70+
}
71+
}
72+
73+
/// Copied from [`Any`](std::any::Any). As casting between trait objects is not possible
74+
/// without indirection, this is used instead.
75+
impl dyn ScriptType + 'static {
76+
#[inline]
77+
pub fn is<T: 'static>(&self) -> bool {
78+
TypeId::of::<T>() == self.type_id()
79+
}
80+
81+
#[inline]
82+
pub fn cast<T: 'static>(&self) -> Option<&T> {
83+
if self.is::<T>() {
84+
// SAFETY: `is` confirmed that the underlying type of the trait object is indeed T.
85+
unsafe { Some(&*(self as *const _ as *const _)) }
86+
} else {
87+
None
88+
}
89+
}
6790
}
6891

6992
/*
@@ -90,11 +113,6 @@ macro_rules! impl_dup {
90113
fn dup(&self) -> Rc<dyn ScriptType> {
91114
Rc::new(self.clone()) as Rc<dyn ScriptType>
92115
}
93-
94-
fn as_any(&self) -> Box<dyn Any> {
95-
// FIXME avoid clone
96-
Box::new(self.clone())
97-
}
98116
};
99117
}
100118

@@ -170,10 +188,6 @@ impl ScriptType for Instance {
170188
fn dup(&self) -> Rc<dyn ScriptType> {
171189
todo!();
172190
}
173-
174-
fn as_any(&self) -> Box<dyn Any> {
175-
todo!();
176-
}
177191
}
178192

179193
impl ScriptType for () {
@@ -203,15 +217,15 @@ impl ScriptType for f64 {
203217
impl_dup!();
204218

205219
fn mul(&self, rhs: &Rc<dyn ScriptType>) -> CallResult<CallError> {
206-
rhs.as_any()
207-
.downcast_ref::<Self>()
220+
rhs
221+
.cast()
208222
.map(|rhs| Rc::new(self * rhs) as Rc<dyn ScriptType>)
209223
.ok_or(CallError::IncompatibleType)
210224
}
211225

212226
fn add(&self, rhs: &Rc<dyn ScriptType>) -> CallResult<CallError> {
213-
rhs.as_any()
214-
.downcast_ref::<Self>()
227+
rhs
228+
.cast()
215229
.map(|rhs| Rc::new(self + rhs) as Rc<dyn ScriptType>)
216230
.ok_or(CallError::IncompatibleType)
217231
}

0 commit comments

Comments
 (0)