Skip to content

Commit 99ad42d

Browse files
committed
Auto merge of #11828 - weihanglo:clippy-disallowed-methods, r=epage
clippy: warn `disallowed_methods` for `std::env::var` and friends
2 parents f2f4496 + 1071cce commit 99ad42d

File tree

15 files changed

+117
-32
lines changed

15 files changed

+117
-32
lines changed

build.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ use std::process::Command;
77
fn main() {
88
commit_info();
99
compress_man();
10-
println!(
11-
"cargo:rustc-env=RUST_HOST_TARGET={}",
12-
std::env::var("TARGET").unwrap()
13-
);
10+
// ALLOWED: Accessing environment during build time shouldn't be prohibited.
11+
#[allow(clippy::disallowed_methods)]
12+
let target = std::env::var("TARGET").unwrap();
13+
println!("cargo:rustc-env=RUST_HOST_TARGET={target}");
1414
}
1515

1616
fn compress_man() {
17+
// ALLOWED: Accessing environment during build time shouldn't be prohibited.
18+
#[allow(clippy::disallowed_methods)]
1719
let out_path = Path::new(&std::env::var("OUT_DIR").unwrap()).join("man.tgz");
1820
let dst = fs::File::create(out_path).unwrap();
1921
let encoder = GzBuilder::new()

clippy.toml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
disallowed-methods = [
2+
{ path = "std::env::var", reason = "Use `Config::get_env` instead. See rust-lang/cargo#11588" },
3+
{ path = "std::env::var_os", reason = "Use `Config::get_env_os` instead. See rust-lang/cargo#11588" },
4+
{ path = "std::env::vars", reason = "Not recommended to use in Cargo. See rust-lang/cargo#11588" },
5+
{ path = "std::env::vars_os", reason = "Not recommended to use in Cargo. See rust-lang/cargo#11588" },
6+
]

src/bin/cargo/cli.rs

+3
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,9 @@ impl GlobalArgs {
413413
}
414414

415415
pub fn cli() -> Command {
416+
// ALLOWED: `RUSTUP_HOME` should only be read from process env, otherwise
417+
// other tools may point to executables from incompatible distributions.
418+
#[allow(clippy::disallowed_methods)]
416419
let is_rustup = std::env::var_os("RUSTUP_HOME").is_some();
417420
let usage = if is_rustup {
418421
"cargo [+toolchain] [OPTIONS] [COMMAND]"

src/bin/cargo/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![warn(rust_2018_idioms)] // while we're getting used to 2018
22
#![allow(clippy::all)]
3+
#![warn(clippy::disallowed_methods)]
34

45
use cargo::util::toml::StringOrVec;
56
use cargo::util::CliError;

src/cargo/core/compiler/custom_build.rs

+8
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,10 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
410410
// If we're opting into backtraces, mention that build dependencies' backtraces can
411411
// be improved by requesting debuginfo to be built, if we're not building with
412412
// debuginfo already.
413+
//
414+
// ALLOWED: Other tools like `rustc` might read it directly
415+
// through `std::env`. We should make their behavior consistent.
416+
#[allow(clippy::disallowed_methods)]
413417
if let Ok(show_backtraces) = std::env::var("RUST_BACKTRACE") {
414418
if !built_with_debuginfo && show_backtraces != "0" {
415419
build_error_context.push_str(&format!(
@@ -727,6 +731,10 @@ impl BuildOutput {
727731
None => return false,
728732
Some(n) => n,
729733
};
734+
// ALLOWED: the process of rustc boostrapping reads this through
735+
// `std::env`. We should make the behavior consistent. Also, we
736+
// don't advertise this for bypassing nightly.
737+
#[allow(clippy::disallowed_methods)]
730738
std::env::var("RUSTC_BOOTSTRAP")
731739
.map_or(false, |var| var.split(',').any(|s| s == name))
732740
};

src/cargo/core/compiler/fingerprint/mod.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,19 @@ pub enum StaleItem {
764764
}
765765

766766
impl LocalFingerprint {
767+
/// Read the environment variable of the given env `key`, and creates a new
768+
/// [`LocalFingerprint::RerunIfEnvChanged`] for it.
769+
///
770+
// TODO: This is allowed at this moment. Should figure out if it makes
771+
// sense if permitting to read env from the config system.
772+
#[allow(clippy::disallowed_methods)]
773+
fn from_env<K: AsRef<str>>(key: K) -> LocalFingerprint {
774+
let key = key.as_ref();
775+
let var = key.to_owned();
776+
let val = env::var(key).ok();
777+
LocalFingerprint::RerunIfEnvChanged { var, val }
778+
}
779+
767780
/// Checks dynamically at runtime if this `LocalFingerprint` has a stale
768781
/// item inside of it.
769782
///
@@ -1661,10 +1674,7 @@ fn local_fingerprints_deps(
16611674
local.extend(
16621675
deps.rerun_if_env_changed
16631676
.iter()
1664-
.map(|var| LocalFingerprint::RerunIfEnvChanged {
1665-
var: var.clone(),
1666-
val: env::var(var).ok(),
1667-
}),
1677+
.map(LocalFingerprint::from_env),
16681678
);
16691679

16701680
local

src/cargo/core/features.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -946,10 +946,7 @@ impl CliUnstable {
946946
self.add(flag, &mut warnings)?;
947947
}
948948

949-
if self.gitoxide.is_none()
950-
&& std::env::var_os("__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2")
951-
.map_or(false, |value| value == "1")
952-
{
949+
if self.gitoxide.is_none() && cargo_use_gitoxide_instead_of_git2() {
953950
self.gitoxide = GitoxideFeatures::safe().into();
954951
}
955952
Ok(warnings)
@@ -1171,9 +1168,15 @@ impl CliUnstable {
11711168

11721169
/// Returns the current release channel ("stable", "beta", "nightly", "dev").
11731170
pub fn channel() -> String {
1171+
// ALLOWED: For testing cargo itself only.
1172+
#[allow(clippy::disallowed_methods)]
11741173
if let Ok(override_channel) = env::var("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS") {
11751174
return override_channel;
11761175
}
1176+
// ALLOWED: the process of rustc boostrapping reads this through
1177+
// `std::env`. We should make the behavior consistent. Also, we
1178+
// don't advertise this for bypassing nightly.
1179+
#[allow(clippy::disallowed_methods)]
11771180
if let Ok(staging) = env::var("RUSTC_BOOTSTRAP") {
11781181
if staging == "1" {
11791182
return "dev".to_string();
@@ -1183,3 +1186,12 @@ pub fn channel() -> String {
11831186
.release_channel
11841187
.unwrap_or_else(|| String::from("dev"))
11851188
}
1189+
1190+
/// Only for testing and developing. See ["Running with gitoxide as default git backend in tests"][1].
1191+
///
1192+
/// [1]: https://doc.crates.io/contrib/tests/running.html#running-with-gitoxide-as-default-git-backend-in-tests
1193+
// ALLOWED: For testing cargo itself only.
1194+
#[allow(clippy::disallowed_methods)]
1195+
fn cargo_use_gitoxide_instead_of_git2() -> bool {
1196+
std::env::var_os("__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2").map_or(false, |value| value == "1")
1197+
}

src/cargo/core/resolver/types.rs

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ pub struct ResolverProgress {
1515
time_to_print: Duration,
1616
printed: bool,
1717
deps_time: Duration,
18+
/// Provides an escape hatch for machine with slow CPU for debugging and
19+
/// testing Cargo itself.
20+
/// See [rust-lang/cargo#6596](https://github.com/rust-lang/cargo/pull/6596) for more.
1821
#[cfg(debug_assertions)]
1922
slow_cpu_multiplier: u64,
2023
}
@@ -31,6 +34,9 @@ impl ResolverProgress {
3134
// Architectures that do not have a modern processor, hardware emulation, etc.
3235
// In the test code we have `slow_cpu_multiplier`, but that is not accessible here.
3336
#[cfg(debug_assertions)]
37+
// ALLOWED: For testing cargo itself only. However, it was communicated as an public
38+
// interface to other developers, so keep it as-is, shouldn't add `__CARGO` prefix.
39+
#[allow(clippy::disallowed_methods)]
3440
slow_cpu_multiplier: std::env::var("CARGO_TEST_SLOW_CPU_MULTIPLIER")
3541
.ok()
3642
.and_then(|m| m.parse().ok())

src/cargo/core/shell.rs

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ impl TtyWidth {
1717
/// Returns the width of the terminal to use for diagnostics (which is
1818
/// relayed to rustc via `--diagnostic-width`).
1919
pub fn diagnostic_terminal_width(&self) -> Option<usize> {
20+
// ALLOWED: For testing cargo itself only.
21+
#[allow(clippy::disallowed_methods)]
2022
if let Ok(width) = std::env::var("__CARGO_TEST_TTY_WIDTH_DO_NOT_USE_THIS") {
2123
return Some(width.parse().unwrap());
2224
}

src/cargo/core/source/source_id.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -428,9 +428,7 @@ impl SourceId {
428428
_ => return false,
429429
}
430430
let url = self.inner.url.as_str();
431-
url == CRATES_IO_INDEX
432-
|| url == CRATES_IO_HTTP_INDEX
433-
|| std::env::var("__CARGO_TEST_CRATES_IO_URL_DO_NOT_USE_THIS").as_deref() == Ok(url)
431+
url == CRATES_IO_INDEX || url == CRATES_IO_HTTP_INDEX || is_overridden_crates_io_url(url)
434432
}
435433

436434
/// Hashes `self`.
@@ -884,3 +882,10 @@ mod tests {
884882
assert_eq!(source_id, deserialized);
885883
}
886884
}
885+
886+
/// Check if `url` equals to the overridden crates.io URL.
887+
// ALLOWED: For testing Cargo itself only.
888+
#[allow(clippy::disallowed_methods)]
889+
fn is_overridden_crates_io_url(url: &str) -> bool {
890+
std::env::var("__CARGO_TEST_CRATES_IO_URL_DO_NOT_USE_THIS").map_or(false, |v| v == url)
891+
}

src/cargo/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// Due to some of the default clippy lints being somewhat subjective and not
55
// necessarily an improvement, we prefer to not use them at this time.
66
#![allow(clippy::all)]
7+
#![warn(clippy::disallowed_methods)]
78
#![warn(clippy::self_named_module_files)]
89
#![allow(rustdoc::private_intra_doc_links)]
910

src/cargo/ops/fix.rs

+36-17
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
//! Cargo begins a normal `cargo check` operation with itself set as a proxy
1818
//! for rustc by setting `primary_unit_rustc` in the build config. When
1919
//! cargo launches rustc to check a crate, it is actually launching itself.
20-
//! The `FIX_ENV` environment variable is set so that cargo knows it is in
20+
//! The `FIX_ENV_INTERNAL` environment variable is set so that cargo knows it is in
2121
//! fix-proxy-mode.
2222
//!
23-
//! Each proxied cargo-as-rustc detects it is in fix-proxy-mode (via `FIX_ENV`
23+
//! Each proxied cargo-as-rustc detects it is in fix-proxy-mode (via `FIX_ENV_INTERNAL`
2424
//! environment variable in `main`) and does the following:
2525
//!
2626
//! - Acquire a lock from the `LockServer` from the master cargo process.
@@ -63,10 +63,20 @@ use crate::util::Config;
6363
use crate::util::{existing_vcs_repo, LockServer, LockServerClient};
6464
use crate::{drop_eprint, drop_eprintln};
6565

66-
const FIX_ENV: &str = "__CARGO_FIX_PLZ";
67-
const BROKEN_CODE_ENV: &str = "__CARGO_FIX_BROKEN_CODE";
68-
const EDITION_ENV: &str = "__CARGO_FIX_EDITION";
69-
const IDIOMS_ENV: &str = "__CARGO_FIX_IDIOMS";
66+
/// **Internal only.**
67+
/// Indicates Cargo is in fix-proxy-mode if presents.
68+
/// The value of it is the socket address of the [`LockServer`] being used.
69+
/// See the [module-level documentation](mod@super::fix) for more.
70+
const FIX_ENV_INTERNAL: &str = "__CARGO_FIX_PLZ";
71+
/// **Internal only.**
72+
/// For passing [`FixOptions::broken_code`] through to cargo running in proxy mode.
73+
const BROKEN_CODE_ENV_INTERNAL: &str = "__CARGO_FIX_BROKEN_CODE";
74+
/// **Internal only.**
75+
/// For passing [`FixOptions::edition`] through to cargo running in proxy mode.
76+
const EDITION_ENV_INTERNAL: &str = "__CARGO_FIX_EDITION";
77+
/// **Internal only.**
78+
/// For passing [`FixOptions::idioms`] through to cargo running in proxy mode.
79+
const IDIOMS_ENV_INTERNAL: &str = "__CARGO_FIX_IDIOMS";
7080

7181
pub struct FixOptions {
7282
pub edition: bool,
@@ -87,20 +97,20 @@ pub fn fix(ws: &Workspace<'_>, opts: &mut FixOptions) -> CargoResult<()> {
8797
// Spin up our lock server, which our subprocesses will use to synchronize fixes.
8898
let lock_server = LockServer::new()?;
8999
let mut wrapper = ProcessBuilder::new(env::current_exe()?);
90-
wrapper.env(FIX_ENV, lock_server.addr().to_string());
100+
wrapper.env(FIX_ENV_INTERNAL, lock_server.addr().to_string());
91101
let _started = lock_server.start()?;
92102

93103
opts.compile_opts.build_config.force_rebuild = true;
94104

95105
if opts.broken_code {
96-
wrapper.env(BROKEN_CODE_ENV, "1");
106+
wrapper.env(BROKEN_CODE_ENV_INTERNAL, "1");
97107
}
98108

99109
if opts.edition {
100-
wrapper.env(EDITION_ENV, "1");
110+
wrapper.env(EDITION_ENV_INTERNAL, "1");
101111
}
102112
if opts.idioms {
103-
wrapper.env(IDIOMS_ENV, "1");
113+
wrapper.env(IDIOMS_ENV_INTERNAL, "1");
104114
}
105115

106116
*opts
@@ -339,7 +349,10 @@ to prevent this issue from happening.
339349
/// Returns `None` if `fix` is not being run (not in proxy mode). Returns
340350
/// `Some(...)` if in `fix` proxy mode
341351
pub fn fix_get_proxy_lock_addr() -> Option<String> {
342-
env::var(FIX_ENV).ok()
352+
// ALLOWED: For the internal mechanism of `cargo fix` only.
353+
// Shouldn't be set directly by anyone.
354+
#[allow(clippy::disallowed_methods)]
355+
env::var(FIX_ENV_INTERNAL).ok()
343356
}
344357

345358
/// Entry point for `cargo` running as a proxy for `rustc`.
@@ -360,7 +373,7 @@ pub fn fix_exec_rustc(config: &Config, lock_addr: &str) -> CargoResult<()> {
360373
.ok();
361374
let mut rustc = ProcessBuilder::new(&args.rustc).wrapped(workspace_rustc.as_ref());
362375
rustc.retry_with_argfile(true);
363-
rustc.env_remove(FIX_ENV);
376+
rustc.env_remove(FIX_ENV_INTERNAL);
364377
args.apply(&mut rustc);
365378

366379
trace!("start rustfixing {:?}", args.file);
@@ -404,7 +417,7 @@ pub fn fix_exec_rustc(config: &Config, lock_addr: &str) -> CargoResult<()> {
404417
// user's code with our changes. Back out everything and fall through
405418
// below to recompile again.
406419
if !output.status.success() {
407-
if config.get_env_os(BROKEN_CODE_ENV).is_none() {
420+
if config.get_env_os(BROKEN_CODE_ENV_INTERNAL).is_none() {
408421
for (path, file) in fixes.files.iter() {
409422
debug!("reverting {:?} due to errors", path);
410423
paths::write(path, &file.original_code)?;
@@ -578,7 +591,7 @@ fn rustfix_and_fix(
578591
// worse by applying fixes where a bug could cause *more* broken code.
579592
// Instead, punt upwards which will reexec rustc over the original code,
580593
// displaying pretty versions of the diagnostics we just read out.
581-
if !output.status.success() && config.get_env_os(BROKEN_CODE_ENV).is_none() {
594+
if !output.status.success() && config.get_env_os(BROKEN_CODE_ENV_INTERNAL).is_none() {
582595
debug!(
583596
"rustfixing `{:?}` failed, rustc exited with {:?}",
584597
filename,
@@ -847,9 +860,15 @@ impl FixArgs {
847860
}
848861

849862
let file = file.ok_or_else(|| anyhow::anyhow!("could not find .rs file in rustc args"))?;
850-
let idioms = env::var(IDIOMS_ENV).is_ok();
851-
852-
let prepare_for_edition = env::var(EDITION_ENV).ok().map(|_| {
863+
// ALLOWED: For the internal mechanism of `cargo fix` only.
864+
// Shouldn't be set directly by anyone.
865+
#[allow(clippy::disallowed_methods)]
866+
let idioms = env::var(IDIOMS_ENV_INTERNAL).is_ok();
867+
868+
// ALLOWED: For the internal mechanism of `cargo fix` only.
869+
// Shouldn't be set directly by anyone.
870+
#[allow(clippy::disallowed_methods)]
871+
let prepare_for_edition = env::var(EDITION_ENV_INTERNAL).ok().map(|_| {
853872
enabled_edition
854873
.unwrap_or(Edition::Edition2015)
855874
.saturating_next()

src/cargo/util/config/environment.rs

+5
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ pub struct Env {
6666
impl Env {
6767
/// Create a new `Env` from process's environment variables.
6868
pub fn new() -> Self {
69+
// ALLOWED: This is the only permissible usage of `std::env::vars{_os}`
70+
// within cargo. If you do need access to individual variables without
71+
// interacting with `Config` system, please use `std::env::var{_os}`
72+
// and justify the validity of the usage.
73+
#[allow(clippy::disallowed_methods)]
6974
let env: HashMap<_, _> = std::env::vars_os().collect();
7075
let (case_insensitive_env, normalized_env) = make_case_insensitive_and_normalized_env(&env);
7176
Self {

src/cargo/util/job.rs

+3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ mod imp {
3232
// when-cargo-is-killed-subprocesses-are-also-killed, but that requires
3333
// one cargo spawned to become its own session leader, so we do that
3434
// here.
35+
//
36+
// ALLOWED: For testing cargo itself only.
37+
#[allow(clippy::disallowed_methods)]
3538
if env::var("__CARGO_TEST_SETSID_PLEASE_DONT_USE_ELSEWHERE").is_ok() {
3639
libc::setsid();
3740
}

src/cargo/util/profile.rs

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ pub struct Profiler {
2222
}
2323

2424
fn enabled_level() -> Option<usize> {
25+
// ALLOWED: for profiling Cargo itself, not intended to be used beyond Cargo contributors.
26+
#[allow(clippy::disallowed_methods)]
2527
env::var("CARGO_PROFILE").ok().and_then(|s| s.parse().ok())
2628
}
2729

0 commit comments

Comments
 (0)