Volatility Considerations for Full Optimization Level
Even if a custom function does not mutate state nor cause side-effects, it may still be volatile, i.e. it depends on external environment and does not guarantee the same result for the same inputs.
A perfect example is a function that gets the current time – obviously each run will return a different value!
print(get_current_time(true)); // prints the current time
// notice the call to 'get_current_time'
// has constant arguments
// The above, under full optimization level, is rewritten to:
print("10:25AM"); // the function call is replaced by
// its result at the time of optimization!
Avoid using OptimizationLevel::Full
if volatile custom functions are involved.
The optimizer, when using OptimizationLevel::Full
, merrily assumes that all functions are
non-volatile, so when it finds constant arguments (or none) it eagerly executes the function
call and replaces it with the result.
This causes the script to behave differently from the intended semantics.
All native functions are assumed to be non-volatile, meaning that they are eagerly called under
OptimizationLevel::Full
when all arguments are constant (or none).
It is possible to mark a function defined within a plugin module as volatile to prevent this behavior.
#[export_module]
mod my_module {
// This function is marked 'volatile' and will not be
// eagerly executed even under OptimizationLevel::Full.
#[rhai_fn(volatile)]
pub get_current_time(am_pm: bool) -> String {
// ...
}
}