Skip to content

Commit da9b1bc

Browse files
committed
Use OsStr in tracked environment variables
1 parent a01330c commit da9b1bc

File tree

5 files changed

+37
-28
lines changed

5 files changed

+37
-28
lines changed

compiler/rustc_interface/messages.ftl

-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ interface_cant_emit_mir =
44
interface_emoji_identifier =
55
identifiers cannot contain emoji: `{$ident}`
66
7-
interface_env_var_not_unicode =
8-
cannot read environment variable "{$key}" with value "{$var}", since it contains non-unicode data
9-
107
interface_error_writing_dependencies =
118
error writing dependencies to `{$path}`: {$error}
129

compiler/rustc_interface/src/errors.rs

-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use std::ffi::OsString;
21
use std::io;
32
use std::path::Path;
43

@@ -22,13 +21,6 @@ pub struct EmojiIdentifier {
2221
pub ident: Symbol,
2322
}
2423

25-
#[derive(Diagnostic)]
26-
#[diag(interface_env_var_not_unicode)]
27-
pub struct EnvVarNotUnicode {
28-
pub key: Symbol,
29-
pub var: OsString,
30-
}
31-
3224
#[derive(Diagnostic)]
3325
#[diag(interface_mixed_bin_crate)]
3426
pub struct MixedBinCrate;

compiler/rustc_interface/src/passes.rs

+20-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::any::Any;
2-
use std::env::VarError;
3-
use std::ffi::OsString;
2+
use std::ffi::{OsStr, OsString};
43
use std::io::{self, BufWriter, Write};
54
use std::path::{Path, PathBuf};
65
use std::sync::{Arc, LazyLock};
@@ -322,22 +321,29 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
322321
)
323322
}
324323

325-
fn env_var(tcx: TyCtxt<'_>, key: Symbol) -> Option<Symbol> {
326-
let var = match env::var(key.as_str()) {
327-
Ok(var) => Some(Symbol::intern(&var)),
328-
Err(VarError::NotPresent) => None,
329-
Err(VarError::NotUnicode(var)) => {
330-
tcx.dcx().emit_err(errors::EnvVarNotUnicode { key, var });
331-
None
332-
}
333-
};
324+
fn env_var_os<'tcx>(tcx: TyCtxt<'tcx>, key: &'tcx OsStr) -> Option<&'tcx OsStr> {
325+
let value = env::var_os(key);
326+
327+
let value_tcx = value.as_deref().map(|value| {
328+
let encoded_bytes = tcx.arena.alloc_slice(value.as_encoded_bytes());
329+
debug_assert_eq!(value.as_encoded_bytes(), encoded_bytes);
330+
// SAFETY: The bytes came from `as_encoded_bytes`, and we assume that
331+
// `alloc_slice` is implemented correctly, and passes the same bytes
332+
// back (debug asserted above).
333+
unsafe { OsStr::from_encoded_bytes_unchecked(encoded_bytes) }
334+
});
335+
334336
// Also add the variable to Cargo's dependency tracking
335337
//
336338
// NOTE: This only works for passes run before `write_dep_info`. See that
337339
// for extension points for configuring environment variables to be
338340
// properly change-tracked.
339-
tcx.sess.psess.env_depinfo.borrow_mut().insert((key, var));
340-
var
341+
tcx.sess.psess.env_depinfo.borrow_mut().insert((
342+
Symbol::intern(&key.to_string_lossy()),
343+
value.and_then(|value| value.to_str()).map(|value| Symbol::intern(&value)),
344+
));
345+
346+
value_tcx
341347
}
342348

343349
// Returns all the paths that correspond to generated files.
@@ -707,7 +713,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
707713
|tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal());
708714
providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1;
709715
providers.early_lint_checks = early_lint_checks;
710-
providers.env_var = env_var;
716+
providers.env_var_os = env_var_os;
711717
proc_macro_decls::provide(providers);
712718
rustc_const_eval::provide(providers);
713719
rustc_middle::hir::provide(providers);

compiler/rustc_middle/src/query/mod.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
#![allow(unused_parens)]
88

9+
use std::ffi::OsStr;
910
use std::mem;
1011
use std::ops::Deref;
1112
use std::path::PathBuf;
@@ -130,9 +131,7 @@ rustc_queries! {
130131
/// NOTE: This currently does not work with dependency info in the
131132
/// analysis, codegen and linking passes, place extra code at the top of
132133
/// `rustc_interface::passes::write_dep_info` to make that work.
133-
///
134-
/// Will emit an error and return `None` if the variable is not UTF-8.
135-
query env_var(key: Symbol) -> Option<Symbol> {
134+
query env_var_os(key: &'tcx OsStr) -> Option<&'tcx OsStr> {
136135
// Environment variables are global state
137136
eval_always
138137
desc { "get the value of an environment variable" }

compiler/rustc_middle/src/util/mod.rs

+15
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@ pub mod call_kind;
33
pub mod common;
44
pub mod find_self_call;
55

6+
use std::env::VarError;
7+
use std::ffi::OsStr;
8+
69
pub use call_kind::{CallDesugaringKind, CallKind, call_kind};
710
pub use find_self_call::find_self_call;
811

12+
use crate::ty::TyCtxt;
13+
914
#[derive(Default, Copy, Clone)]
1015
pub struct Providers {
1116
pub queries: rustc_middle::query::Providers,
@@ -29,3 +34,13 @@ impl std::ops::Deref for Providers {
2934
&self.queries
3035
}
3136
}
37+
38+
impl<'tcx> TyCtxt<'tcx> {
39+
pub fn env_var(self, key: &'tcx OsStr) -> Result<&'tcx str, VarError> {
40+
if let Some(value) = self.env_var_os(key.as_ref()) {
41+
value.to_str().ok_or_else(|| VarError::NotUnicode(value.to_os_string()))
42+
} else {
43+
Err(VarError::NotPresent)
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)