1
1
use crate :: bytecode:: { ByteCode , CallResult , Environment , RunError } ;
2
- use core:: any:: Any ;
2
+ use core:: any:: { Any , TypeId } ;
3
3
use core:: fmt:: Debug ;
4
4
use core:: ops:: { Add , Mul } ;
5
5
use rustc_hash:: FxHashMap ;
@@ -47,23 +47,46 @@ pub enum CallError {
47
47
AlreadyBorrowed ,
48
48
}
49
49
50
- pub trait ScriptType : Debug + Any {
50
+ pub trait ScriptType : Debug + ' static {
51
51
fn call ( & self , function : & str , args : & [ Rc < dyn ScriptType > ] ) -> CallResult < CallError > ;
52
52
53
53
fn dup ( & self ) -> Rc < dyn ScriptType > ;
54
54
55
+ #[ inline]
55
56
fn mul ( & self , rhs : & Rc < dyn ScriptType > ) -> CallResult < CallError > {
56
57
let _ = rhs;
57
58
Err ( CallError :: InvalidOperator )
58
59
}
59
60
61
+ #[ inline]
60
62
fn add ( & self , rhs : & Rc < dyn ScriptType > ) -> CallResult < CallError > {
61
63
let _ = rhs;
62
64
Err ( CallError :: InvalidOperator )
63
65
}
64
66
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
+ }
67
90
}
68
91
69
92
/*
@@ -90,11 +113,6 @@ macro_rules! impl_dup {
90
113
fn dup( & self ) -> Rc <dyn ScriptType > {
91
114
Rc :: new( self . clone( ) ) as Rc <dyn ScriptType >
92
115
}
93
-
94
- fn as_any( & self ) -> Box <dyn Any > {
95
- // FIXME avoid clone
96
- Box :: new( self . clone( ) )
97
- }
98
116
} ;
99
117
}
100
118
@@ -170,10 +188,6 @@ impl ScriptType for Instance {
170
188
fn dup ( & self ) -> Rc < dyn ScriptType > {
171
189
todo ! ( ) ;
172
190
}
173
-
174
- fn as_any ( & self ) -> Box < dyn Any > {
175
- todo ! ( ) ;
176
- }
177
191
}
178
192
179
193
impl ScriptType for ( ) {
@@ -203,15 +217,15 @@ impl ScriptType for f64 {
203
217
impl_dup ! ( ) ;
204
218
205
219
fn mul ( & self , rhs : & Rc < dyn ScriptType > ) -> CallResult < CallError > {
206
- rhs. as_any ( )
207
- . downcast_ref :: < Self > ( )
220
+ rhs
221
+ . cast ( )
208
222
. map ( |rhs| Rc :: new ( self * rhs) as Rc < dyn ScriptType > )
209
223
. ok_or ( CallError :: IncompatibleType )
210
224
}
211
225
212
226
fn add ( & self , rhs : & Rc < dyn ScriptType > ) -> CallResult < CallError > {
213
- rhs. as_any ( )
214
- . downcast_ref :: < Self > ( )
227
+ rhs
228
+ . cast ( )
215
229
. map ( |rhs| Rc :: new ( self + rhs) as Rc < dyn ScriptType > )
216
230
. ok_or ( CallError :: IncompatibleType )
217
231
}
0 commit comments