diff --git a/src/env/environment.rs b/src/env/environment.rs index 86704bbf4..4ee0cfe2c 100644 --- a/src/env/environment.rs +++ b/src/env/environment.rs @@ -188,7 +188,7 @@ impl EnvStack { /// Return whether we are the principal stack. pub fn is_principal(&self) -> bool { - std::ptr::eq(self, &**Self::principal()) + std::ptr::eq(self, Self::principal()) } /// Helpers to get and set the proc statuses. @@ -367,10 +367,10 @@ impl EnvStack { } /// Access the principal variable stack, associated with the principal parser. - pub fn principal() -> &'static Arc { + pub fn principal() -> &'static EnvStack { use std::sync::OnceLock; - static PRINCIPAL_STACK: OnceLock> = OnceLock::new(); - &PRINCIPAL_STACK.get_or_init(|| Arc::new(EnvStack::new())) + static PRINCIPAL_STACK: OnceLock = OnceLock::new(); + &PRINCIPAL_STACK.get_or_init(|| EnvStack::new()) } pub fn set_argv(&self, argv: Vec) { @@ -554,7 +554,7 @@ fn setup_path() { pub static INHERITED_VARS: OnceCell> = OnceCell::new(); pub fn env_init(paths: Option<&ConfigPaths>, do_uvars: bool, default_paths: bool) { - let vars = &**EnvStack::principal(); + let vars = EnvStack::principal(); let env_iter: Vec<_> = std::env::vars_os() .map(|(k, v)| (str2wcstring(k.as_bytes()), str2wcstring(v.as_bytes()))) diff --git a/src/parser.rs b/src/parser.rs index 4c343e85d..7840e2cf1 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -402,18 +402,13 @@ impl Parser { pub fn principal_parser() -> &'static Parser { use std::cell::OnceCell; static PRINCIPAL: MainThread> = MainThread::new(OnceCell::new()); - &PRINCIPAL - .get() - // The parser is !Send/!Sync and strictly single-threaded, but we can have - // multi-threaded access to its variables stack (why, though?) so EnvStack::principal() - // returns an Arc instead of an Rc. Since the Arc is - // statically allocated and always valid (not even destroyed on exit), we can safely - // transform the Arc into an Rc and save Parser from needing atomic ref counting - // to manage its further references. - .get_or_init(|| { - let env_rc = unsafe { Rc::from_raw(&**EnvStack::principal() as *const _) }; - Parser::new(env_rc, true) - }) + &PRINCIPAL.get().get_or_init(|| { + // Safety: EnvStack::principal() returns a `static` variable guaranteed to always be + // alive. We just don't want to hard-code the lifetime in `Parser` so we wrap the + // `EnvStack` in an `Rc` before sending it along. + let env_rc = unsafe { Rc::from_raw(EnvStack::principal() as *const _) }; + Parser::new(env_rc, true) + }) } /// Assert that this parser is allowed to execute on the current thread.