From 4d54b4ceb4fd32059bd5e35ffc4fa7992d71bd29 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 1 Dec 2024 12:04:36 +0100 Subject: [PATCH] Use OsStr in tracked environment variables --- compiler/rustc_interface/messages.ftl | 3 --- compiler/rustc_interface/src/errors.rs | 8 ------ compiler/rustc_interface/src/passes.rs | 34 +++++++++++++++----------- compiler/rustc_middle/src/query/mod.rs | 5 ++-- compiler/rustc_middle/src/util/mod.rs | 13 ++++++++++ 5 files changed, 35 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl index 7c98f07586350..47dfbc1d7fbf1 100644 --- a/compiler/rustc_interface/messages.ftl +++ b/compiler/rustc_interface/messages.ftl @@ -4,9 +4,6 @@ interface_cant_emit_mir = interface_emoji_identifier = identifiers cannot contain emoji: `{$ident}` -interface_env_var_not_unicode = - cannot read environment variable "{$key}" with value "{$var}", since it contains non-unicode data - interface_error_writing_dependencies = error writing dependencies to `{$path}`: {$error} diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index e7ef7d2f375fa..939980a932fdb 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -1,4 +1,3 @@ -use std::ffi::OsString; use std::io; use std::path::Path; @@ -22,13 +21,6 @@ pub struct EmojiIdentifier { pub ident: Symbol, } -#[derive(Diagnostic)] -#[diag(interface_env_var_not_unicode)] -pub struct EnvVarNotUnicode { - pub key: Symbol, - pub var: OsString, -} - #[derive(Diagnostic)] #[diag(interface_mixed_bin_crate)] pub struct MixedBinCrate; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index e6ca0ed937b88..31a1fa20d4f74 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1,6 +1,5 @@ use std::any::Any; -use std::env::VarError; -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; use std::io::{self, BufWriter, Write}; use std::path::{Path, PathBuf}; use std::sync::{Arc, LazyLock}; @@ -322,22 +321,29 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { ) } -fn env_var(tcx: TyCtxt<'_>, key: Symbol) -> Option { - let var = match env::var(key.as_str()) { - Ok(var) => Some(Symbol::intern(&var)), - Err(VarError::NotPresent) => None, - Err(VarError::NotUnicode(var)) => { - tcx.dcx().emit_err(errors::EnvVarNotUnicode { key, var }); - None - } - }; +fn env_var_os<'tcx>(tcx: TyCtxt<'tcx>, key: &'tcx OsStr) -> Option<&'tcx OsStr> { + let value = env::var_os(key); + + let value_tcx = value.as_deref().map(|value| { + let encoded_bytes = tcx.arena.alloc_slice(value.as_encoded_bytes()); + debug_assert_eq!(value.as_encoded_bytes(), encoded_bytes); + // SAFETY: The bytes came from `as_encoded_bytes`, and we assume that + // `alloc_slice` is implemented correctly, and passes the same bytes + // back (debug asserted above). + unsafe { OsStr::from_encoded_bytes_unchecked(encoded_bytes) } + }); + // Also add the variable to Cargo's dependency tracking // // NOTE: This only works for passes run before `write_dep_info`. See that // for extension points for configuring environment variables to be // properly change-tracked. - tcx.sess.psess.env_depinfo.borrow_mut().insert((key, var)); - var + tcx.sess.psess.env_depinfo.borrow_mut().insert(( + Symbol::intern(&key.to_string_lossy()), + value.and_then(|value| value.to_str()).map(|value| Symbol::intern(&value)), + )); + + value_tcx } // Returns all the paths that correspond to generated files. @@ -707,7 +713,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { |tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal()); providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1; providers.early_lint_checks = early_lint_checks; - providers.env_var = env_var; + providers.env_var_os = env_var_os; proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0f9c741afa0b2..c1529c6a425cd 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -6,6 +6,7 @@ #![allow(unused_parens)] +use std::ffi::OsStr; use std::mem; use std::ops::Deref; use std::path::PathBuf; @@ -130,9 +131,7 @@ rustc_queries! { /// NOTE: This currently does not work with dependency info in the /// analysis, codegen and linking passes, place extra code at the top of /// `rustc_interface::passes::write_dep_info` to make that work. - /// - /// Will emit an error and return `None` if the variable is not UTF-8. - query env_var(key: Symbol) -> Option { + query env_var_os(key: &'tcx OsStr) -> Option<&'tcx OsStr> { // Environment variables are global state eval_always desc { "get the value of an environment variable" } diff --git a/compiler/rustc_middle/src/util/mod.rs b/compiler/rustc_middle/src/util/mod.rs index 8dafc42264485..86dd0d1ccdd6a 100644 --- a/compiler/rustc_middle/src/util/mod.rs +++ b/compiler/rustc_middle/src/util/mod.rs @@ -3,6 +3,9 @@ pub mod call_kind; pub mod common; pub mod find_self_call; +use std::env::VarError; +use std::ffi::OsStr; + pub use call_kind::{CallDesugaringKind, CallKind, call_kind}; pub use find_self_call::find_self_call; @@ -29,3 +32,13 @@ impl std::ops::Deref for Providers { &self.queries } } + +impl<'tcx> TyCtxt<'tcx> { + pub fn env_var(key: impl AsRef) -> Result<&'tcx str, VarError> { + if let Some(value) = self.env_var_os(key.as_ref()) { + value.into_string().map_err(VarError::NotUnicode) + } else { + Err(VarError::NotPresent) + } + } +}