Somewhat counter-intuitively, this code is active when compiling under *Linux*
and is always false when compiling under Windows. The logic was incorrectly
reversed before (it's easier to reason about when you realize that fish doesn't
even compile under Windows because it uses tons of libc functions).
As the code was actually never compiled, it wasn't actually tested for validity
either and there were some issues that prevented it from compiling that have
since been fixed. The logic has also been adjusted a bit to make it possible to
use the rust-native int parsing instead of `libc::strtod()`.
The code has been changed to use `once_cell::race::OnceBool` instead of
`once_cell::sync::Lazy<T>` which imposes a greater runtime burden with locking
and other overhead. We don't care if the code runs more than once on init (if
calls were to race, though they probably don't) - just that the code isn't
subsequently executed on each call. The `once_cell::race` module is a better fit
here, though it doesn't expose the ergonomic `Lazy<T>` façade around its types.
is_main_thread() and co were previously ported to threads.rs, so remove the
duplicate code and move everything else related to threads there as well. No
need for common.rs to be as long as our old common.cpp!
I left #[deprecated] stubs in common.rs to help redirect anyone porting code
over that we can remove after the port has finished.
Additionally, the fork guards had previously been left as a todo!() item but I
ported that over. They're all called from the now-central threads::init()
function so there isn't a need to call each individual thread-management-fn
manually.
The decision was made a while back to try and embrace/use the native rust thread
functionality and utilities so the manual thread management code has been ripped
out and was replaced with code that marshals the native rust values instead. The
values won't line up with what the C++ code sees, but it never lined up anyway
since each was using a separate counter to keep track of the values.
There are many places where we want to treat a missing variable the same as
a variable with an empty value.
In C++ we handle this by branching on maybe_t<env_var_t>::missing_or_empty().
If it returns false, we go on to access maybe_t<env_var_t>::value() aka
operator*.
In Rust, Environment::get() will return an Option<EnvVar>.
We could define a MissingOrEmpty trait and implement it for Option<EnvVar>.
However that will still leave us with ugly calls to Option::unwrap()
(by convention Rust does use shorthands like *).
Let's add a variable getter that returns none for empty variables.
This isn't the same as "join"/"join0", where one is just a special
case of the other.
These are two different, if basically opposite commands.
But more importantly this was a huge mess and the formatting was broken.
Except for the indent visitor bits.
Tests for parse_util_detect_errors* are not ported yet because they depend
on expand.h (and operation_context.h which depends on env.h).
This caused math to assert out because it never wrote into the buffer.
Now, presumably it wrote somewhere but I don't know where, so fixing
this seems like a good idea.
Fixes#9735.