Default parameters via #[opt(default = ...)] syntax #1396 
     +327   −44      
   Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.    
 
Closes #381.
Allows Rust functions to provide default values via parameter attribute
#[opt(default = ...)]syntax.Example
This can be called from GDScript as follows:
The expressions
"str",100implementAsArg<GString>andAsArg<i32>, respectively.This means that by-ref types (arrays, objects, etc) must be passed with
&value.Open questions
1. Should we cache and reuse values?
#[opt(default = ...)]expression on each call. What may sound silly avoids the Python "default has different value next time" problem. More on that below.Variantconversions + array allocation. So it's not obvious how big of an impact re-evaluating has.2. Do we allow mutable defaults?
The Python problem arises when two conditions are true: default values are reused, and they are mutable.
If we don't cache, an independent object is provided every time.
If we disallow mutable values, we need to limit the types:
Copyvalues are always fine (ints, floats, bools, vectors, transforms, colors, ...)GString,StringName,NodePath,PackedArray)set_metaetc.)into_read_only()We could allow mutable types but with special opt-in, e.g.:
3. Unification with
#[init(val = ...)]The attribute used for field initialization,
#[init(val = ...)], is very similar in its nature. Historically, it works however onTvalues and notAsArg<T>impls, which makes some expressions a bit different.Mid-term it can make sense to align the two to use the same syntax, in either direction.
Conservative + incremental approach
As long as there are still uncertainties, I'd like to expose this functionality step-by-step. Starting with only a subset (e.g. limited to some "safe" types) would allow a more organic expansion over time, with feedback from users and concrete patterns emerging.
Especially questions like "is the default reused or not" have a lot of potential for subtle bugs if we change them later, so I'd rather disallow certain designs initially, until it turns out what works best.
Future work
Lots of things can still be done:
#[func]which doesn't use#[opt]has no perf disadvantages. Allocations should be postponed until it's clear that defaults are needed.register-docs)