@@ -44,7 +44,12 @@ pub fn make_function_definition_with_defaults(
4444 builder_fields,
4545 builder_args,
4646 builder_inits,
47- } = make_extender ( sig, object_fn_param, default_fn_params) ;
47+ } = make_extender (
48+ sig. name ( ) ,
49+ object_fn_param,
50+ & required_fn_params,
51+ & default_fn_params,
52+ ) ;
4853
4954 // ExBuilder::new() constructor signature.
5055 let FnParamTokens {
@@ -61,19 +66,6 @@ pub fn make_function_definition_with_defaults(
6166 ) ;
6267 let required_params_builder_constructor = & required_params_class_methods;
6368
64- // Parameters for some_function() and some_function_ex().
65- // TODO collapse with next assignment. Maybe next 2
66- /*let FnParamTokens {
67- params: required_params_class_methods,
68- ..
69- } = functions_common::make_params_exprs(
70- required_fn_params.iter().cloned(),
71- true,
72- true,
73- false,
74- false,
75- );*/
76-
7769 // Forwarded args by some_function() and some_function_ex().
7870 let FnParamTokens {
7971 arg_names : required_args_internal,
@@ -92,13 +84,15 @@ pub fn make_function_definition_with_defaults(
9284 // then we need to annotate the _ex() function with an explicit lifetime. Also adjust &self -> &'a self.
9385 let receiver_self = & code. receiver . self_prefix ;
9486
95- let ( builder_ret_lifetime, receiver_param) ;
96- if let Some ( func_lifetime) = func_general_lifetime. as_ref ( ) {
97- builder_ret_lifetime = Some ( func_lifetime) ;
98- receiver_param = & code. receiver . param_lifetime_a ;
87+ let ( simple_receiver_param, extended_receiver_param, func_or_builder_lifetime) ;
88+ if let Some ( func_lt) = func_general_lifetime. as_ref ( ) . or ( builder_lifetime. as_ref ( ) ) {
89+ simple_receiver_param = & code. receiver . param ;
90+ extended_receiver_param = & code. receiver . param_lifetime_a ;
91+ func_or_builder_lifetime = Some ( func_lt) ;
9992 } else {
100- builder_ret_lifetime = None ;
101- receiver_param = & code. receiver . param ;
93+ simple_receiver_param = & code. receiver . param ;
94+ extended_receiver_param = & code. receiver . param ;
95+ func_or_builder_lifetime = None ;
10296 } ;
10397
10498 // Technically, the builder would not need a lifetime -- it could just maintain an `object_ptr` copy.
@@ -146,7 +140,7 @@ pub fn make_function_definition_with_defaults(
146140 #[ doc = #default_parameter_usage]
147141 #[ inline]
148142 #vis fn #simple_fn_name #func_general_lifetime (
149- #receiver_param
143+ #simple_receiver_param
150144 #( #required_params_class_methods, ) *
151145 ) #return_decl {
152146 #receiver_self #extended_fn_name(
@@ -157,10 +151,10 @@ pub fn make_function_definition_with_defaults(
157151 // _ex() function:
158152 // Lifetime is set if any parameter is a reference OR if the method is not static/global (and thus can refer to self).
159153 #[ inline]
160- #vis fn #extended_fn_name #func_general_lifetime (
161- #receiver_param
154+ #vis fn #extended_fn_name #func_or_builder_lifetime (
155+ #extended_receiver_param
162156 #( #required_params_class_methods, ) *
163- ) -> #builder_ty #builder_ret_lifetime {
157+ ) -> #builder_ty #builder_lifetime {
164158 #builder_ty:: new(
165159 #object_arg
166160 #( #required_args_internal, ) *
@@ -278,26 +272,34 @@ fn make_extender_receiver(sig: &dyn Function) -> ExtenderReceiver {
278272}
279273
280274fn make_extender (
281- sig : & dyn Function ,
282- object_fn_param : Option < FnParam > ,
283- default_fn_params : Vec < & FnParam > ,
275+ fn_name : & str ,
276+ receiver_param : Option < FnParam > ,
277+ required_params : & [ & FnParam ] ,
278+ default_params : & [ & FnParam ] ,
284279) -> Extender {
285280 // Note: could build a documentation string with default values here, but the Rust tokens are not very readable,
286281 // and often not helpful, such as Enum::from_ord(13). Maybe one day those could be resolved and curated.
287282
288- let lifetime = if sig. qualifier ( ) . is_static_or_global ( ) {
289- None
290- } else {
283+ let all_fn_params = receiver_param
284+ . iter ( )
285+ . chain ( required_params. iter ( ) . cloned ( ) )
286+ . chain ( default_params. iter ( ) . cloned ( ) ) ;
287+ let len = all_fn_params. size_hint ( ) . 0 ;
288+
289+ // If builder is a method with a receiver OR any *required* parameter is by-ref, use lifetime.
290+ // Default parameters cannot be by-ref, since they need to store a default value. Potential optimization later.
291+ let lifetime = if receiver_param. is_some ( ) // !sig.qualifier().is_static_or_global()
292+ || required_params. iter ( ) . any ( |p| p. type_ . is_pass_by_ref ( ) )
293+ {
291294 Some ( quote ! { <' a> } )
295+ } else {
296+ None
292297 } ;
293298
294- let all_fn_params = object_fn_param. iter ( ) . chain ( sig. params ( ) . iter ( ) ) ;
295- let len = all_fn_params. size_hint ( ) . 0 ;
296-
297299 let mut result = Extender {
298- builder_ty : format_ident ! ( "Ex{}" , conv:: to_pascal_case( sig . name ( ) ) ) ,
300+ builder_ty : format_ident ! ( "Ex{}" , conv:: to_pascal_case( fn_name ) ) ,
299301 builder_lifetime : lifetime,
300- builder_methods : Vec :: with_capacity ( default_fn_params . len ( ) ) ,
302+ builder_methods : Vec :: with_capacity ( default_params . len ( ) ) ,
301303 builder_fields : Vec :: with_capacity ( len) ,
302304 builder_args : Vec :: with_capacity ( len) ,
303305 builder_inits : Vec :: with_capacity ( len) ,
@@ -316,7 +318,6 @@ fn make_extender(
316318 let init = if let Some ( value) = default_value {
317319 make_field_init ( name, Some ( value) , conversion)
318320 } else {
319- //quote! { #name }
320321 make_field_init ( name, None , conversion)
321322 } ;
322323
@@ -336,7 +337,7 @@ fn make_extender(
336337 result. builder_inits . push ( init) ;
337338 }
338339
339- for param in default_fn_params {
340+ for param in default_params {
340341 let FnParam { name, type_, .. } = param;
341342 let param_type = type_. param_decl ( ) ;
342343 let ( _, field_needs_conversion) = default_extender_field_decl ( type_, true ) ;
@@ -397,9 +398,9 @@ fn make_field_init(
397398 match ( conversion, expr) {
398399 ( Conv :: ObjectArg , Some ( expr) ) => quote ! { #name: #expr. consume_object( ) } ,
399400 ( Conv :: ObjectArg , None ) /*. */ => quote ! { #name: #name. consume_object( ) } ,
400- ( Conv :: Reference , Some ( expr ) ) => quote ! { #name : & #expr } ,
401- ( Conv :: Reference , None ) /*. */ => quote ! { #name : & #name } ,
402- ( Conv :: None | Conv :: ReferenceWithDefault , Some ( expr) ) => quote ! { #name: #expr } ,
403- ( Conv :: None | Conv :: ReferenceWithDefault , None ) /*. */ => quote ! { #name } ,
401+
402+ // Currently no differentiation between None|Reference|ReferenceWithDefault; this may change...
403+ ( Conv :: None | Conv :: Reference | Conv :: ReferenceWithDefault , Some ( expr) ) => quote ! { #name: #expr } ,
404+ ( Conv :: None | Conv :: Reference | Conv :: ReferenceWithDefault , None ) /*. */ => quote ! { #name } ,
404405 }
405406}
0 commit comments