Skip to content

Commit 553d580

Browse files
committed
Add typo suggestion for a misspelt Cargo environment variable
1 parent 401ae55 commit 553d580

File tree

6 files changed

+220
-0
lines changed

6 files changed

+220
-0
lines changed

compiler/rustc_builtin_macros/messages.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ builtin_macros_duplicate_macro_attribute = duplicated attribute
156156
157157
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
158158
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
159+
.cargo_typo = there is a similar Cargo environment variable: `{$suggested_var}`
159160
.custom = use `std::env::var({$var_expr})` to read the variable at run time
160161
161162
builtin_macros_env_not_unicode = environment variable `{$var}` is not a valid Unicode string

compiler/rustc_builtin_macros/src/env.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_ast::token::{self, LitKind};
1010
use rustc_ast::tokenstream::TokenStream;
1111
use rustc_ast::{ExprKind, GenericArg, Mutability};
1212
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
13+
use rustc_span::edit_distance::edit_distance;
1314
use rustc_span::{Ident, Span, Symbol, kw, sym};
1415
use thin_vec::thin_vec;
1516

@@ -144,6 +145,12 @@ pub(crate) fn expand_env<'cx>(
144145
if let Some(msg_from_user) = custom_msg {
145146
cx.dcx()
146147
.emit_err(errors::EnvNotDefinedWithUserMessage { span, msg_from_user })
148+
} else if let Some(suggested_var) = find_similar_cargo_var(var.as_str()) {
149+
cx.dcx().emit_err(errors::EnvNotDefined::CargoEnvVarTypo {
150+
span,
151+
var: *symbol,
152+
suggested_var: Symbol::intern(suggested_var),
153+
})
147154
} else if is_cargo_env_var(var.as_str()) {
148155
cx.dcx().emit_err(errors::EnvNotDefined::CargoEnvVar {
149156
span,
@@ -176,3 +183,49 @@ fn is_cargo_env_var(var: &str) -> bool {
176183
|| var.starts_with("DEP_")
177184
|| matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET")
178185
}
186+
187+
const KNOWN_CARGO_VARS: &[&str] = &[
188+
// List of known Cargo environment variables that are set for crates (not build scripts, OUT_DIR etc).
189+
// See: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates
190+
"CARGO_PKG_VERSION",
191+
"CARGO_PKG_VERSION_MAJOR",
192+
"CARGO_PKG_VERSION_MINOR",
193+
"CARGO_PKG_VERSION_PATCH",
194+
"CARGO_PKG_VERSION_PRE",
195+
"CARGO_PKG_AUTHORS",
196+
"CARGO_PKG_NAME",
197+
"CARGO_PKG_DESCRIPTION",
198+
"CARGO_PKG_HOMEPAGE",
199+
"CARGO_PKG_REPOSITORY",
200+
"CARGO_PKG_LICENSE",
201+
"CARGO_PKG_LICENSE_FILE",
202+
"CARGO_PKG_RUST_VERSION",
203+
"CARGO_PKG_README",
204+
"CARGO_MANIFEST_DIR",
205+
"CARGO_MANIFEST_PATH",
206+
"CARGO_CRATE_NAME",
207+
"CARGO_BIN_NAME",
208+
"CARGO_PRIMARY_PACKAGE",
209+
];
210+
211+
fn find_similar_cargo_var(var: &str) -> Option<&'static str> {
212+
if !var.starts_with("CARGO_") {
213+
return None;
214+
}
215+
216+
let lookup_len = var.chars().count();
217+
let max_dist = std::cmp::max(lookup_len, 3) / 3;
218+
let mut best_match = None;
219+
let mut best_distance = usize::MAX;
220+
221+
for &known_var in KNOWN_CARGO_VARS {
222+
if let Some(distance) = edit_distance(var, known_var, max_dist) {
223+
if distance < best_distance {
224+
best_distance = distance;
225+
best_match = Some(known_var);
226+
}
227+
}
228+
}
229+
230+
best_match
231+
}

compiler/rustc_builtin_macros/src/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,14 @@ pub(crate) enum EnvNotDefined<'a> {
535535
var_expr: &'a rustc_ast::Expr,
536536
},
537537
#[diag(builtin_macros_env_not_defined)]
538+
#[help(builtin_macros_cargo_typo)]
539+
CargoEnvVarTypo {
540+
#[primary_span]
541+
span: Span,
542+
var: Symbol,
543+
suggested_var: Symbol,
544+
},
545+
#[diag(builtin_macros_env_not_defined)]
538546
#[help(builtin_macros_custom)]
539547
CustomEnvVar {
540548
#[primary_span]
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//@ edition: 2021
2+
3+
// Regression test for issue #148439
4+
// Ensure that when using misspelled Cargo environment variables in env!(),
5+
6+
fn test_cargo_package_version() {
7+
let _ = env!("CARGO_PACKAGE_VERSION");
8+
//~^ ERROR environment variable `CARGO_PACKAGE_VERSION` not defined at compile time
9+
//~| HELP there is a similar Cargo environment variable: `CARGO_PKG_VERSION`
10+
}
11+
12+
fn test_cargo_package_name() {
13+
let _ = env!("CARGO_PACKAGE_NAME");
14+
//~^ ERROR environment variable `CARGO_PACKAGE_NAME` not defined at compile time
15+
//~| HELP there is a similar Cargo environment variable: `CARGO_PKG_NAME`
16+
}
17+
18+
fn test_cargo_package_authors() {
19+
let _ = env!("CARGO_PACKAGE_AUTHORS");
20+
//~^ ERROR environment variable `CARGO_PACKAGE_AUTHORS` not defined at compile time
21+
//~| HELP there is a similar Cargo environment variable: `CARGO_PKG_AUTHORS`
22+
}
23+
24+
fn test_cargo_manifest_directory() {
25+
let _ = env!("CARGO_MANIFEST_DIRECTORY");
26+
//~^ ERROR environment variable `CARGO_MANIFEST_DIRECTORY` not defined at compile time
27+
//~| HELP there is a similar Cargo environment variable: `CARGO_MANIFEST_DIR`
28+
}
29+
30+
fn test_cargo_pkg_version_typo() {
31+
let _ = env!("CARGO_PKG_VERSIO");
32+
//~^ ERROR environment variable `CARGO_PKG_VERSIO` not defined at compile time
33+
//~| HELP there is a similar Cargo environment variable: `CARGO_PKG_VERSION`
34+
}
35+
36+
fn test_non_cargo_var() {
37+
// Non-Cargo variable should get different help message
38+
let _ = env!("MY_CUSTOM_VAR");
39+
//~^ ERROR environment variable `MY_CUSTOM_VAR` not defined at compile time
40+
//~| HELP use `std::env::var("MY_CUSTOM_VAR")` to read the variable at run time
41+
}
42+
43+
fn test_cargo_unknown_var() {
44+
// Cargo-prefixed but not similar to any known variable
45+
let _ = env!("CARGO_SOMETHING_TOTALLY_UNKNOWN");
46+
//~^ ERROR environment variable `CARGO_SOMETHING_TOTALLY_UNKNOWN` not defined at compile time
47+
//~| HELP Cargo sets build script variables at run time. Use `std::env::var("CARGO_SOMETHING_TOTALLY_UNKNOWN")` instead
48+
}
49+
50+
fn main() {}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
error: environment variable `CARGO_PACKAGE_VERSION` not defined at compile time
2+
--> $DIR/env-cargo-var-typo-issue-148439.rs:7:13
3+
|
4+
LL | let _ = env!("CARGO_PACKAGE_VERSION");
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: there is a similar Cargo environment variable: `CARGO_PKG_VERSION`
8+
9+
error: environment variable `CARGO_PACKAGE_NAME` not defined at compile time
10+
--> $DIR/env-cargo-var-typo-issue-148439.rs:13:13
11+
|
12+
LL | let _ = env!("CARGO_PACKAGE_NAME");
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
|
15+
= help: there is a similar Cargo environment variable: `CARGO_PKG_NAME`
16+
17+
error: environment variable `CARGO_PACKAGE_AUTHORS` not defined at compile time
18+
--> $DIR/env-cargo-var-typo-issue-148439.rs:19:13
19+
|
20+
LL | let _ = env!("CARGO_PACKAGE_AUTHORS");
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
22+
|
23+
= help: there is a similar Cargo environment variable: `CARGO_PKG_AUTHORS`
24+
25+
error: environment variable `CARGO_MANIFEST_DIRECTORY` not defined at compile time
26+
--> $DIR/env-cargo-var-typo-issue-148439.rs:25:13
27+
|
28+
LL | let _ = env!("CARGO_MANIFEST_DIRECTORY");
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
|
31+
= help: there is a similar Cargo environment variable: `CARGO_MANIFEST_DIR`
32+
33+
error: environment variable `CARGO_PKG_VERSIO` not defined at compile time
34+
--> $DIR/env-cargo-var-typo-issue-148439.rs:31:13
35+
|
36+
LL | let _ = env!("CARGO_PKG_VERSIO");
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^
38+
|
39+
= help: there is a similar Cargo environment variable: `CARGO_PKG_VERSION`
40+
41+
error: environment variable `MY_CUSTOM_VAR` not defined at compile time
42+
--> $DIR/env-cargo-var-typo-issue-148439.rs:38:13
43+
|
44+
LL | let _ = env!("MY_CUSTOM_VAR");
45+
| ^^^^^^^^^^^^^^^^^^^^^
46+
|
47+
= help: use `std::env::var("MY_CUSTOM_VAR")` to read the variable at run time
48+
49+
error: environment variable `CARGO_SOMETHING_TOTALLY_UNKNOWN` not defined at compile time
50+
--> $DIR/env-cargo-var-typo-issue-148439.rs:45:13
51+
|
52+
LL | let _ = env!("CARGO_SOMETHING_TOTALLY_UNKNOWN");
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
54+
|
55+
= help: Cargo sets build script variables at run time. Use `std::env::var("CARGO_SOMETHING_TOTALLY_UNKNOWN")` instead
56+
57+
error: aborting due to 7 previous errors
58+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//@ edition: 2021
2+
3+
// Regression test for issue #148439
4+
// Ensure that when using misspelled Cargo environment variables in env!(),
5+
6+
fn test_cargo_package_version() {
7+
let _ = env!("CARGO_PACKAGE_VERSION");
8+
//~^ ERROR environment variable `CARGO_PACKAGE_VERSION` not defined at compile time
9+
//~| HELP there is a similar Cargo environment variable: `CARGO_PKG_VERSION`
10+
}
11+
12+
fn test_cargo_package_name() {
13+
let _ = env!("CARGO_PACKAGE_NAME");
14+
//~^ ERROR environment variable `CARGO_PACKAGE_NAME` not defined at compile time
15+
//~| HELP there is a similar Cargo environment variable: `CARGO_PKG_NAME`
16+
}
17+
18+
fn test_cargo_package_authors() {
19+
let _ = env!("CARGO_PACKAGE_AUTHORS");
20+
//~^ ERROR environment variable `CARGO_PACKAGE_AUTHORS` not defined at compile time
21+
//~| HELP there is a similar Cargo environment variable: `CARGO_PKG_AUTHORS`
22+
}
23+
24+
fn test_cargo_manifest_directory() {
25+
let _ = env!("CARGO_MANIFEST_DIRECTORY");
26+
//~^ ERROR environment variable `CARGO_MANIFEST_DIRECTORY` not defined at compile time
27+
//~| HELP there is a similar Cargo environment variable: `CARGO_MANIFEST_DIR`
28+
}
29+
30+
fn test_cargo_pkg_version_typo() {
31+
let _ = env!("CARGO_PKG_VERSIO");
32+
//~^ ERROR environment variable `CARGO_PKG_VERSIO` not defined at compile time
33+
//~| HELP there is a similar Cargo environment variable: `CARGO_PKG_VERSION`
34+
}
35+
36+
fn test_non_cargo_var() {
37+
// Non-Cargo variable should get different help message
38+
let _ = env!("MY_CUSTOM_VAR");
39+
//~^ ERROR environment variable `MY_CUSTOM_VAR` not defined at compile time
40+
//~| HELP use `std::env::var("MY_CUSTOM_VAR")` to read the variable at run time
41+
}
42+
43+
fn test_cargo_unknown_var() {
44+
// Cargo-prefixed but not similar to any known variable
45+
let _ = env!("CARGO_SOMETHING_TOTALLY_UNKNOWN");
46+
//~^ ERROR environment variable `CARGO_SOMETHING_TOTALLY_UNKNOWN` not defined at compile time
47+
//~| HELP Cargo sets build script variables at run time. Use `std::env::var("CARGO_SOMETHING_TOTALLY_UNKNOWN")` instead
48+
}
49+
50+
fn main() {}

0 commit comments

Comments
 (0)