@@ -20,6 +20,7 @@ use crate::util::ident;
20
20
// ----------------------------------------------------------------------------------------------------------------------------------------------
21
21
// Godot -> Rust types
22
22
23
+ /// Returns `(identifier, is_copy)` for a hardcoded Rust type, if it exists.
23
24
fn to_hardcoded_rust_ident ( full_ty : & GodotTy ) -> Option < & str > {
24
25
let ty = full_ty. ty . as_str ( ) ;
25
26
let meta = full_ty. meta . as_deref ( ) ;
@@ -95,13 +96,25 @@ pub(crate) fn to_rust_type_abi(ty: &str, ctx: &mut Context) -> (RustTy, bool) {
95
96
"Object*" => {
96
97
is_obj = true ;
97
98
RustTy :: RawPointer {
98
- inner : Box :: new ( RustTy :: BuiltinIdent ( ident ( "c_void" ) ) ) ,
99
+ inner : Box :: new ( RustTy :: BuiltinIdent {
100
+ ty : ident ( "c_void" ) ,
101
+ is_copy : true ,
102
+ } ) ,
99
103
is_const : false ,
100
104
}
101
105
}
102
- "int" => RustTy :: BuiltinIdent ( ident ( "i32" ) ) ,
103
- "float" => RustTy :: BuiltinIdent ( ident ( "f32" ) ) ,
104
- "double" => RustTy :: BuiltinIdent ( ident ( "f64" ) ) ,
106
+ "int" => RustTy :: BuiltinIdent {
107
+ ty : ident ( "i32" ) ,
108
+ is_copy : true ,
109
+ } ,
110
+ "float" => RustTy :: BuiltinIdent {
111
+ ty : ident ( "f32" ) ,
112
+ is_copy : true ,
113
+ } ,
114
+ "double" => RustTy :: BuiltinIdent {
115
+ ty : ident ( "f64" ) ,
116
+ is_copy : true ,
117
+ } ,
105
118
_ => to_rust_type ( ty, None , ctx) ,
106
119
} ;
107
120
@@ -137,6 +150,7 @@ fn to_rust_type_uncached(full_ty: &GodotTy, ctx: &mut Context) -> RustTy {
137
150
if is_builtin_type_scalar ( ty) {
138
151
ident ( ty)
139
152
} else {
153
+ // Convert as-is. Includes StringName and NodePath.
140
154
TyName :: from_godot ( ty) . rust_ty
141
155
}
142
156
}
@@ -163,7 +177,10 @@ fn to_rust_type_uncached(full_ty: &GodotTy, ctx: &mut Context) -> RustTy {
163
177
// Only place where meta is relevant is here.
164
178
if !ty. starts_with ( "typedarray::" ) {
165
179
if let Some ( hardcoded) = to_hardcoded_rust_ident ( full_ty) {
166
- return RustTy :: BuiltinIdent ( ident ( hardcoded) ) ;
180
+ return RustTy :: BuiltinIdent {
181
+ ty : ident ( hardcoded) ,
182
+ is_copy : ctx. is_builtin_copy ( hardcoded) ,
183
+ } ;
167
184
}
168
185
}
169
186
@@ -182,7 +199,10 @@ fn to_rust_type_uncached(full_ty: &GodotTy, ctx: &mut Context) -> RustTy {
182
199
} else if let Some ( packed_arr_ty) = ty. strip_prefix ( "Packed" ) {
183
200
// Don't trigger on PackedScene ;P
184
201
if packed_arr_ty. ends_with ( "Array" ) {
185
- return RustTy :: BuiltinIdent ( rustify_ty ( ty) ) ;
202
+ return RustTy :: BuiltinIdent {
203
+ ty : rustify_ty ( ty) ,
204
+ is_copy : false , // Packed arrays are not Copy.
205
+ } ;
186
206
}
187
207
} else if let Some ( elem_ty) = ty. strip_prefix ( "typedarray::" ) {
188
208
let rust_elem_ty = to_rust_type ( elem_ty, full_ty. meta . as_ref ( ) , ctx) ;
@@ -200,8 +220,12 @@ fn to_rust_type_uncached(full_ty: &GodotTy, ctx: &mut Context) -> RustTy {
200
220
201
221
// Note: do not check if it's a known engine class, because that will not work in minimal mode (since not all classes are stored)
202
222
if ctx. is_builtin ( ty) || ctx. is_native_structure ( ty) {
203
- // Unchanged
204
- RustTy :: BuiltinIdent ( rustify_ty ( ty) )
223
+ // Unchanged.
224
+ // Native structures might not all be Copy, but they should have value semantics.
225
+ RustTy :: BuiltinIdent {
226
+ ty : rustify_ty ( ty) ,
227
+ is_copy : ctx. is_builtin_copy ( ty) ,
228
+ }
205
229
} else {
206
230
let ty = rustify_ty ( ty) ;
207
231
let qualified_class = quote ! { crate :: classes:: #ty } ;
@@ -263,7 +287,9 @@ fn to_rust_expr_inner(expr: &str, ty: &RustTy, is_inner: bool) -> TokenStream {
263
287
"{}" => return quote ! { Dictionary :: new( ) } ,
264
288
"null" => {
265
289
return match ty {
266
- RustTy :: BuiltinIdent ( ident) if ident == "Variant" => quote ! { Variant :: nil( ) } ,
290
+ RustTy :: BuiltinIdent { ty : ident, .. } if ident == "Variant" => {
291
+ quote ! { Variant :: nil( ) }
292
+ }
267
293
RustTy :: EngineClass { .. } => {
268
294
quote ! { Gd :: null_arg( ) }
269
295
}
@@ -273,8 +299,8 @@ fn to_rust_expr_inner(expr: &str, ty: &RustTy, is_inner: bool) -> TokenStream {
273
299
// empty string appears only for Callable/Rid in 4.0; default ctor syntax in 4.1+
274
300
"" | "RID()" | "Callable()" if !is_inner => {
275
301
return match ty {
276
- RustTy :: BuiltinIdent ( ident) if ident == "Rid" => quote ! { Rid :: Invalid } ,
277
- RustTy :: BuiltinIdent ( ident) if ident == "Callable" => {
302
+ RustTy :: BuiltinIdent { ty : ident, .. } if ident == "Rid" => quote ! { Rid :: Invalid } ,
303
+ RustTy :: BuiltinIdent { ty : ident, .. } if ident == "Callable" => {
278
304
quote ! { Callable :: invalid( ) }
279
305
}
280
306
_ => panic ! ( "empty string not representable in target type {ty:?}" ) ,
@@ -295,9 +321,11 @@ fn to_rust_expr_inner(expr: &str, ty: &RustTy, is_inner: bool) -> TokenStream {
295
321
is_bitfield : false , ..
296
322
} => quote ! { crate :: obj:: EngineEnum :: from_ord( #lit) } ,
297
323
298
- RustTy :: BuiltinIdent ( ident) if ident == "Variant" => quote ! { Variant :: from( #lit) } ,
324
+ RustTy :: BuiltinIdent { ty : ident, .. } if ident == "Variant" => {
325
+ quote ! { Variant :: from( #lit) }
326
+ }
299
327
300
- RustTy :: BuiltinIdent ( ident)
328
+ RustTy :: BuiltinIdent { ty : ident, .. }
301
329
if ident == "i64" || ident == "f64" || unmap_meta ( ty) . is_some ( ) =>
302
330
{
303
331
suffixed_lit ( num, ident)
@@ -313,7 +341,9 @@ fn to_rust_expr_inner(expr: &str, ty: &RustTy, is_inner: bool) -> TokenStream {
313
341
// Float literals (some floats already handled by integer literals)
314
342
if let Ok ( num) = expr. parse :: < f64 > ( ) {
315
343
return match ty {
316
- RustTy :: BuiltinIdent ( ident) if ident == "f64" || unmap_meta ( ty) . is_some ( ) => {
344
+ RustTy :: BuiltinIdent { ty : ident, .. }
345
+ if ident == "f64" || unmap_meta ( ty) . is_some ( ) =>
346
+ {
317
347
suffixed_lit ( num, ident)
318
348
}
319
349
_ if is_inner => {
@@ -331,7 +361,7 @@ fn to_rust_expr_inner(expr: &str, ty: &RustTy, is_inner: bool) -> TokenStream {
331
361
quote ! { #expr }
332
362
} else {
333
363
match ty {
334
- RustTy :: BuiltinIdent ( ident)
364
+ RustTy :: BuiltinIdent { ty : ident, .. }
335
365
if ident == "GString" || ident == "StringName" || ident == "NodePath" =>
336
366
{
337
367
quote ! { #ident:: from( #expr) }
@@ -429,16 +459,28 @@ fn gdscript_to_rust_expr() {
429
459
// The 'None' type is used to simulate absence of type information. Some tests are commented out, because this functionality is not
430
460
// yet needed. If we ever want to reuse to_rust_expr() in other contexts, we could re-enable them.
431
461
432
- let ty_int = RustTy :: BuiltinIdent ( ident ( "i64" ) ) ;
462
+ let ty_int = RustTy :: BuiltinIdent {
463
+ ty : ident ( "i64" ) ,
464
+ is_copy : true ,
465
+ } ;
433
466
let ty_int = Some ( & ty_int) ;
434
467
435
- let ty_int_u16 = RustTy :: BuiltinIdent ( ident ( "u16" ) ) ;
468
+ let ty_int_u16 = RustTy :: BuiltinIdent {
469
+ ty : ident ( "u16" ) ,
470
+ is_copy : true ,
471
+ } ;
436
472
let ty_int_u16 = Some ( & ty_int_u16) ;
437
473
438
- let ty_float = RustTy :: BuiltinIdent ( ident ( "f64" ) ) ;
474
+ let ty_float = RustTy :: BuiltinIdent {
475
+ ty : ident ( "f64" ) ,
476
+ is_copy : true ,
477
+ } ;
439
478
let ty_float = Some ( & ty_float) ;
440
479
441
- let ty_float_f32 = RustTy :: BuiltinIdent ( ident ( "f32" ) ) ;
480
+ let ty_float_f32 = RustTy :: BuiltinIdent {
481
+ ty : ident ( "f32" ) ,
482
+ is_copy : true ,
483
+ } ;
442
484
let ty_float_f32 = Some ( & ty_float_f32) ;
443
485
444
486
let ty_enum = RustTy :: EngineEnum {
@@ -455,7 +497,10 @@ fn gdscript_to_rust_expr() {
455
497
} ;
456
498
let ty_bitfield = Some ( & ty_bitfield) ;
457
499
458
- let ty_variant = RustTy :: BuiltinIdent ( ident ( "Variant" ) ) ;
500
+ let ty_variant = RustTy :: BuiltinIdent {
501
+ ty : ident ( "Variant" ) ,
502
+ is_copy : false ,
503
+ } ;
459
504
let ty_variant = Some ( & ty_variant) ;
460
505
461
506
// let ty_object = RustTy::EngineClass {
@@ -464,13 +509,22 @@ fn gdscript_to_rust_expr() {
464
509
// };
465
510
// let ty_object = Some(&ty_object);
466
511
467
- let ty_string = RustTy :: BuiltinIdent ( ident ( "GString" ) ) ;
512
+ let ty_string = RustTy :: BuiltinIdent {
513
+ ty : ident ( "GString" ) ,
514
+ is_copy : true ,
515
+ } ;
468
516
let ty_string = Some ( & ty_string) ;
469
517
470
- let ty_stringname = RustTy :: BuiltinIdent ( ident ( "StringName" ) ) ;
518
+ let ty_stringname = RustTy :: BuiltinIdent {
519
+ ty : ident ( "StringName" ) ,
520
+ is_copy : true ,
521
+ } ;
471
522
let ty_stringname = Some ( & ty_stringname) ;
472
523
473
- let ty_nodepath = RustTy :: BuiltinIdent ( ident ( "NodePath" ) ) ;
524
+ let ty_nodepath = RustTy :: BuiltinIdent {
525
+ ty : ident ( "NodePath" ) ,
526
+ is_copy : true ,
527
+ } ;
474
528
let ty_nodepath = Some ( & ty_nodepath) ;
475
529
476
530
#[ rustfmt:: skip]
@@ -581,7 +635,7 @@ fn gdscript_to_rust_expr() {
581
635
///
582
636
/// Avoids dragging along the meta type through [`RustTy::BuiltinIdent`].
583
637
pub ( crate ) fn unmap_meta ( rust_ty : & RustTy ) -> Option < Ident > {
584
- let RustTy :: BuiltinIdent ( rust_ty) = rust_ty else {
638
+ let RustTy :: BuiltinIdent { ty : rust_ty, .. } = rust_ty else {
585
639
return None ;
586
640
} ;
587
641
0 commit comments