@@ -10,7 +10,7 @@ use crate::models::domain::{
10
10
BuildConfiguration , BuiltinClass , BuiltinMethod , BuiltinSize , BuiltinVariant , Class ,
11
11
ClassCommons , ClassConstant , ClassConstantValue , ClassMethod , ClassSignal , Constructor , Enum ,
12
12
Enumerator , EnumeratorValue , ExtensionApi , FnDirection , FnParam , FnQualifier , FnReturn ,
13
- FunctionCommon , GodotApiVersion , ModName , NativeStructure , Operator , Singleton , TyName ,
13
+ FunctionCommon , GodotApiVersion , ModName , NativeStructure , Operator , RustTy , Singleton , TyName ,
14
14
UtilityFunction ,
15
15
} ;
16
16
use crate :: models:: json:: {
@@ -374,6 +374,7 @@ impl BuiltinMethod {
374
374
is_vararg : method. is_vararg ,
375
375
is_private : false , // See 'exposed' below. Could be special_cases::is_method_private(builtin_name, &method.name),
376
376
is_virtual_required : false ,
377
+ is_unsafe : false , // Builtin methods don't use raw pointers.
377
378
direction : FnDirection :: Outbound {
378
379
hash : method. hash . expect ( "hash absent for builtin method" ) ,
379
380
} ,
@@ -456,6 +457,7 @@ impl ClassMethod {
456
457
} ,
457
458
} ;
458
459
460
+ // May still be renamed further, for unsafe methods. Not done here because data to determine safety is not available yet.
459
461
let rust_method_name = Self :: make_virtual_method_name ( class_name, & method. name ) ;
460
462
461
463
Self :: from_json_inner ( method, rust_method_name, class_name, direction, ctx)
@@ -488,7 +490,7 @@ impl ClassMethod {
488
490
// Since Godot 4.4, GDExtension advertises whether virtual methods have a default implementation or are required to be overridden.
489
491
#[ cfg( before_api = "4.4" ) ]
490
492
let is_virtual_required =
491
- special_cases:: is_virtual_method_required ( & class_name, rust_method_name ) ;
493
+ special_cases:: is_virtual_method_required ( & class_name, & method . name ) ;
492
494
493
495
#[ cfg( since_api = "4.4" ) ]
494
496
#[ allow( clippy:: let_and_return) ]
@@ -507,15 +509,29 @@ impl ClassMethod {
507
509
is_required_in_json
508
510
} ;
509
511
512
+ let parameters = FnParam :: new_range ( & method. arguments , ctx) ;
513
+ let return_value = FnReturn :: new ( & method. return_value , ctx) ;
514
+ let is_unsafe = Self :: function_uses_pointers ( & parameters, & return_value) ;
515
+
516
+ // Future note: if further changes are made to the virtual method name, make sure to make it reversible so that #[godot_api]
517
+ // can match on the Godot name of the virtual method.
518
+ let rust_method_name = if is_unsafe && method. is_virtual {
519
+ // If the method is unsafe, we need to rename it to avoid conflicts with the safe version.
520
+ conv:: make_unsafe_virtual_fn_name ( rust_method_name)
521
+ } else {
522
+ rust_method_name. to_string ( )
523
+ } ;
524
+
510
525
Some ( Self {
511
526
common : FunctionCommon {
512
- name : rust_method_name. to_string ( ) ,
527
+ name : rust_method_name,
513
528
godot_name : godot_method_name,
514
- parameters : FnParam :: new_range ( & method . arguments , ctx ) ,
515
- return_value : FnReturn :: new ( & method . return_value , ctx ) ,
529
+ parameters,
530
+ return_value,
516
531
is_vararg : method. is_vararg ,
517
532
is_private,
518
533
is_virtual_required,
534
+ is_unsafe,
519
535
direction,
520
536
} ,
521
537
qualifier,
@@ -524,12 +540,28 @@ impl ClassMethod {
524
540
}
525
541
526
542
fn make_virtual_method_name < ' m > ( class_name : & TyName , godot_method_name : & ' m str ) -> & ' m str {
527
- // Remove leading underscore from virtual method names.
528
- let method_name = godot_method_name
543
+ // Hardcoded overrides.
544
+ if let Some ( rust_name) =
545
+ special_cases:: maybe_rename_virtual_method ( class_name, godot_method_name)
546
+ {
547
+ return rust_name;
548
+ }
549
+
550
+ // In general, just rlemove leading underscore from virtual method names.
551
+ godot_method_name
529
552
. strip_prefix ( '_' )
530
- . unwrap_or ( godot_method_name) ;
553
+ . unwrap_or ( godot_method_name)
554
+ }
555
+
556
+ fn function_uses_pointers ( parameters : & [ FnParam ] , return_value : & FnReturn ) -> bool {
557
+ let has_pointer_params = parameters
558
+ . iter ( )
559
+ . any ( |param| matches ! ( param. type_, RustTy :: RawPointer { .. } ) ) ;
560
+
561
+ let has_pointer_return = matches ! ( return_value. type_, Some ( RustTy :: RawPointer { .. } ) ) ;
531
562
532
- special_cases:: maybe_rename_virtual_method ( class_name, method_name)
563
+ // No short-circuiting due to variable decls, but that's fine.
564
+ has_pointer_params || has_pointer_return
533
565
}
534
566
}
535
567
@@ -584,6 +616,7 @@ impl UtilityFunction {
584
616
is_vararg : function. is_vararg ,
585
617
is_private,
586
618
is_virtual_required : false ,
619
+ is_unsafe : false , // Utility functions don't use raw pointers.
587
620
direction : FnDirection :: Outbound {
588
621
hash : function. hash ,
589
622
} ,
0 commit comments