11use crate :: bytecode:: { ByteCode , CallResult , Environment , RunError } ;
2- use core:: any:: Any ;
2+ use core:: any:: { Any , TypeId } ;
33use core:: fmt:: Debug ;
44use core:: ops:: { Add , Mul } ;
55use 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
179193impl 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