Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add environment variable query #130883

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions compiler/rustc_borrowck/src/nll.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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};

Expand Down Expand Up @@ -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)))
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_errors/src/diagnostic_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_interface/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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}

Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_interface/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::ffi::OsString;
use std::io;
use std::path::Path;

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

fn env_var(tcx: TyCtxt<'_>, key: Symbol) -> Option<Symbol> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was unsure where to put the query definition, so I just put it in the same file as some other general queries.

let var = match std::env::var(key.as_str()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there something similar to Clippy's disallowed-methods that I could use to lint against usage of std::env::var in the compiler, and direct users towards the query instead?

See also rust-lang/cargo#11588.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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));
Comment on lines +349 to +350
Copy link
Contributor Author

@madsmtm madsmtm Sep 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, a complication here is that this query will only work with the dependency info files that Cargo reads if it's called before passes::write_dep_info at:

passes::write_dep_info(tcx);

So everything done during passes::analysis and Linker::codegen_and_build_linker will need some other mechanism for populating ParseSess::env_depinfo.

Is it possible for us to move the write_dep_info pass to the very end, or just before linking? Or is it important that it happens as soon as possible for parallelizing Cargo, or something?

var
}

// Returns all the paths that correspond to generated files.
fn generated_output_paths(
tcx: TyCtxt<'_>,
Expand Down Expand Up @@ -623,6 +638,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;
proc_macro_decls::provide(providers);
rustc_const_eval::provide(providers);
rustc_middle::hir::provide(providers);
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_lint/src/non_local_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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_) => {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/query/erase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ trivial! {
Option<rustc_span::def_id::DefId>,
Option<rustc_span::def_id::LocalDefId>,
Option<rustc_span::Span>,
Option<rustc_span::Symbol>,
Option<rustc_target::abi::FieldIdx>,
Option<rustc_target::spec::PanicStrategy>,
Option<usize>,
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Symbol> {
// 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" }
Expand Down
Loading