@@ -98,7 +98,6 @@ pub struct FnParamTokens {
9898 /// Generic argument list `<'a0, 'a1, ...>` after `type CallSig`, if available.
9999 pub callsig_lifetime_args : Option < TokenStream > ,
100100 pub arg_exprs : Vec < TokenStream > ,
101- pub func_general_lifetime : Option < TokenStream > ,
102101}
103102
104103pub fn make_function_definition (
@@ -142,7 +141,6 @@ pub fn make_function_definition(
142141 callsig_param_types : param_types,
143142 callsig_lifetime_args,
144143 arg_exprs : arg_names,
145- func_general_lifetime : fn_lifetime,
146144 } = if sig. is_virtual ( ) {
147145 make_params_exprs_virtual ( sig. params ( ) . iter ( ) , sig)
148146 } else {
@@ -175,11 +173,14 @@ pub fn make_function_definition(
175173 default_structs_code = TokenStream :: new ( ) ;
176174 } ;
177175
176+ let maybe_func_generic_params = sig. return_value ( ) . generic_params ( ) ;
177+ let maybe_func_generic_bounds = sig. return_value ( ) . where_clause ( ) ;
178+
178179 let call_sig_decl = {
179180 let return_ty = & sig. return_value ( ) . type_tokens ( ) ;
180181
181182 quote ! {
182- type CallRet = #return_ty;
183+ type CallRet #maybe_func_generic_params = #return_ty;
183184 type CallParams #callsig_lifetime_args = ( #( #param_types, ) * ) ;
184185 }
185186 } ;
@@ -279,10 +280,12 @@ pub fn make_function_definition(
279280
280281 quote ! {
281282 #maybe_safety_doc
282- #vis #maybe_unsafe fn #primary_fn_name #fn_lifetime (
283+ #vis #maybe_unsafe fn #primary_fn_name #maybe_func_generic_params (
283284 #receiver_param
284285 #( #params, ) *
285- ) #return_decl {
286+ ) #return_decl
287+ #maybe_func_generic_bounds
288+ {
286289 #call_sig_decl
287290
288291 let args = ( #( #arg_names, ) * ) ;
@@ -357,10 +360,7 @@ pub(crate) enum FnKind {
357360 /// `call()` forwarding to `try_call()`.
358361 DelegateTry ,
359362
360- /// Default extender `new()` associated function -- optional receiver and required parameters.
361- ExBuilderConstructor ,
362-
363- /// Same as [`ExBuilderConstructor`], but for a builder with an explicit lifetime.
363+ /// Default extender `new()` associated function -- optional receiver and required parameters. Has an explicit lifetime.
364364 ExBuilderConstructorLifetimed ,
365365
366366 /// Default extender `new()` associated function -- only default parameters.
@@ -489,6 +489,7 @@ pub(crate) fn make_param_or_field_type(
489489 ..
490490 }
491491 | RustTy :: BuiltinArray { .. }
492+ | RustTy :: GenericArray
492493 | RustTy :: EngineArray { .. } => {
493494 let lft = lifetimes. next ( ) ;
494495 special_ty = Some ( quote ! { RefArg <#lft, #ty> } ) ;
@@ -572,7 +573,6 @@ pub(crate) fn make_params_exprs<'a>(
572573 // Methods relevant in the context of default parameters. Flow in this order.
573574 // Note that for builder methods of Ex* structs, there's a direct call in default_parameters.rs to the parameter manipulation methods,
574575 // bypassing this method. So one case is missing here.
575- FnKind :: ExBuilderConstructor => ( FnParamDecl :: FnPublic , FnArgExpr :: StoreInField ) ,
576576 FnKind :: ExBuilderConstructorLifetimed => {
577577 ( FnParamDecl :: FnPublicLifetime , FnArgExpr :: StoreInField )
578578 }
@@ -603,6 +603,32 @@ pub(crate) fn make_params_exprs<'a>(
603603 ret
604604}
605605
606+ /// Returns the type for a virtual method parameter.
607+ ///
608+ /// Generates `Option<Gd<T>>` instead of `Gd<T>` for object parameters (which are currently all nullable).
609+ ///
610+ /// Used for consistency between virtual trait definitions and `type Sig = ...` type-safety declarations
611+ /// (which are used to improve compile-time errors on mismatch).
612+ pub ( crate ) fn make_virtual_param_type (
613+ param_ty : & RustTy ,
614+ param_name : & Ident ,
615+ function_sig : & dyn Function ,
616+ ) -> TokenStream {
617+ match param_ty {
618+ // Virtual methods accept Option<Gd<T>>, since we don't know whether objects are nullable or required.
619+ RustTy :: EngineClass { .. }
620+ if !special_cases:: is_class_method_param_required (
621+ function_sig. surrounding_class ( ) . unwrap ( ) ,
622+ function_sig. godot_name ( ) ,
623+ param_name,
624+ ) =>
625+ {
626+ quote ! { Option <#param_ty> }
627+ }
628+ _ => quote ! { #param_ty } ,
629+ }
630+ }
631+
606632/// For virtual functions, returns the parameter declarations, type tokens, and names.
607633pub ( crate ) fn make_params_exprs_virtual < ' a > (
608634 method_args : impl Iterator < Item = & ' a FnParam > ,
@@ -614,30 +640,13 @@ pub(crate) fn make_params_exprs_virtual<'a>(
614640 let param_name = & param. name ;
615641 let param_ty = & param. type_ ;
616642
617- match & param. type_ {
618- // Virtual methods accept Option<Gd<T>>, since we don't know whether objects are nullable or required.
619- RustTy :: EngineClass { .. }
620- if !special_cases:: is_class_method_param_required (
621- function_sig. surrounding_class ( ) . unwrap ( ) ,
622- function_sig. godot_name ( ) ,
623- param_name,
624- ) =>
625- {
626- ret. param_decls
627- . push ( quote ! { #param_name: Option <#param_ty> } ) ;
628- ret. arg_exprs . push ( quote ! { #param_name } ) ;
629- ret. callsig_param_types . push ( quote ! { #param_ty } ) ;
630- }
643+ // Map parameter types (e.g. virtual functions need Option<Gd> instead of Gd).
644+ let param_ty_tokens = make_virtual_param_type ( param_ty, param_name, function_sig) ;
631645
632- // All other methods and parameter types: standard handling.
633- // For now, virtual methods always receive their parameter by value.
634- //_ => ret.push_regular(param_name, param_ty, true, false, false),
635- _ => {
636- ret. param_decls . push ( quote ! { #param_name: #param_ty } ) ;
637- ret. arg_exprs . push ( quote ! { #param_name } ) ;
638- ret. callsig_param_types . push ( quote ! { #param_ty } ) ;
639- }
640- }
646+ ret. param_decls
647+ . push ( quote ! { #param_name: #param_ty_tokens } ) ;
648+ ret. arg_exprs . push ( quote ! { #param_name } ) ;
649+ ret. callsig_param_types . push ( quote ! { #param_ty } ) ;
641650 }
642651
643652 ret
0 commit comments