diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index d85af52b01e36..a47ac980eb0b8 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -1,9 +1,9 @@ //! The entry point of the NLL borrow checker. +use std::io; use std::path::PathBuf; use std::rc::Rc; use std::str::FromStr; -use std::{env, io}; use polonius_engine::{Algorithm, Output}; use rustc_data_structures::fx::FxIndexMap; @@ -21,6 +21,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_session::config::MirIncludeSpans; +use rustc_span::Symbol; use rustc_span::symbol::sym; use tracing::{debug, instrument}; @@ -179,9 +180,11 @@ pub(crate) fn compute_regions<'a, 'tcx>( } if polonius_output { - let algorithm = - env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid")); - let algorithm = Algorithm::from_str(&algorithm).unwrap(); + let algorithm = infcx + .tcx + .env_var(Symbol::intern("POLONIUS_ALGORITHM")) + .unwrap_or_else(|| Symbol::intern("Hybrid")); + let algorithm = Algorithm::from_str(algorithm.as_str()).unwrap(); debug!("compute_regions: using polonius algorithm {:?}", algorithm); let _prof_timer = infcx.tcx.prof.generic_activity("polonius_analysis"); Some(Rc::new(Output::compute(all_facts, algorithm, false))) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 19529f06ef1d2..9bde6aab72968 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -242,6 +242,12 @@ impl IntoDiagArg for std::ffi::CString { } } +impl IntoDiagArg for std::ffi::OsString { + fn into_diag_arg(self) -> DiagArgValue { + DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned())) + } +} + impl IntoDiagArg for rustc_data_structures::small_c_str::SmallCStr { fn into_diag_arg(self) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned())) diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl index 47dfbc1d7fbf1..7c98f07586350 100644 --- a/compiler/rustc_interface/messages.ftl +++ b/compiler/rustc_interface/messages.ftl @@ -4,6 +4,9 @@ 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 939980a932fdb..e7ef7d2f375fa 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -1,3 +1,4 @@ +use std::ffi::OsString; use std::io; use std::path::Path; @@ -21,6 +22,13 @@ 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 bba517915a2df..4a61d1a1eec54 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1,4 +1,5 @@ use std::any::Any; +use std::env::VarError; use std::ffi::OsString; use std::io::{self, BufWriter, Write}; use std::path::{Path, PathBuf}; @@ -336,6 +337,20 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { ) } +fn env_var(tcx: TyCtxt<'_>, key: Symbol) -> Option { + let var = match std::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 + } + }; + // Also add the variable to Cargo's dependency tracking + tcx.sess.psess.env_depinfo.borrow_mut().insert((key, var)); + var +} + // Returns all the paths that correspond to generated files. fn generated_output_paths( tcx: TyCtxt<'_>, @@ -623,6 +638,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; proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 56f930ea7f62e..86375c1b93762 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::symbol::kw; -use rustc_span::{ExpnKind, MacroKind, Span, sym}; +use rustc_span::{ExpnKind, MacroKind, Span, Symbol, sym}; use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag}; use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; @@ -105,8 +105,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { // determining if we are in a doctest context can't currently be determined // by the code itself (there are no specific attributes), but fortunately rustdoc // sets a perma-unstable env var for libtest so we just reuse that for now - let is_at_toplevel_doctest = - || self.body_depth == 2 && std::env::var("UNSTABLE_RUSTDOC_TEST_PATH").is_ok(); + let is_at_toplevel_doctest = || { + self.body_depth == 2 + && cx.tcx.env_var(Symbol::intern("UNSTABLE_RUSTDOC_TEST_PATH")).is_some() + }; match item.kind { ItemKind::Impl(impl_) => { diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 48bf4ffced0ce..8e5232c2bd861 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -253,6 +253,7 @@ trivial! { Option, Option, Option, + Option, Option, Option, Option, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9609ef46d5c31..3d9d774ca4bc0 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -118,6 +118,16 @@ rustc_queries! { desc { "perform lints prior to macro expansion" } } + /// Useful for the implementation of `std::env!`, `proc-macro`s change + /// detection and target-dependent compiler flags. + /// + /// Will emit an error and return `None` if the variable is not UTF-8. + query env_var(key: Symbol) -> Option { + // Environment variables are global state + eval_always + desc { "get the value of an environment variable" } + } + query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { no_hash desc { "getting the resolver outputs" }