Skip to content

Commit

Permalink
Use OsStr in tracked environment variables
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Dec 1, 2024
1 parent a01330c commit 4d54b4c
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 28 deletions.
3 changes: 0 additions & 3 deletions compiler/rustc_interface/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_interface/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::ffi::OsString;
use std::io;
use std::path::Path;

Expand All @@ -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;
Expand Down
34 changes: 20 additions & 14 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -322,22 +321,29 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
)
}

fn env_var(tcx: TyCtxt<'_>, key: Symbol) -> Option<Symbol> {
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.
Expand Down Expand Up @@ -707,7 +713,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = 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);
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#![allow(unused_parens)]

use std::ffi::OsStr;
use std::mem;
use std::ops::Deref;
use std::path::PathBuf;
Expand Down Expand Up @@ -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<Symbol> {
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" }
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_middle/src/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -29,3 +32,13 @@ impl std::ops::Deref for Providers {
&self.queries
}
}

impl<'tcx> TyCtxt<'tcx> {
pub fn env_var(key: impl AsRef<OsStr>) -> 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)
}
}
}

0 comments on commit 4d54b4c

Please sign in to comment.