Skip to content

Commit e104299

Browse files
authored
fix(new): Improve quality of package name error messages (#16398)
### What does this PR try to resolve? While triaging #16396, I noticed that the error messages don't match the rustc style which we are aiming for, so I tweaked the messages and went ahead and fixed #16396. Fixes #16396 ### How to test and review this PR? Since `different-binary-name` doesn't have a `-Z` variant, I held off on suggesting it so we didn't suggest using an unstable feature.
2 parents a7cdba1 + 214f69e commit e104299

File tree

4 files changed

+79
-66
lines changed

4 files changed

+79
-66
lines changed

src/cargo/ops/cargo_new.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -174,16 +174,18 @@ fn check_name(
174174
// If --name is already used to override, no point in suggesting it
175175
// again as a fix.
176176
let name_help = if show_name_help {
177-
"\nIf you need a package name to not match the directory name, consider using --name flag."
177+
"\nnote: the directory name is used as the package name\
178+
\nhelp: to override the package name, pass `--name <pkgname>`"
178179
} else {
179180
""
180181
};
181182
let bin_help = || {
182183
let mut help = String::from(name_help);
183-
if has_bin && !name.is_empty() {
184+
// Only suggest `bin.name` for valid crate names because it is used for `--crate`
185+
if has_bin && validate_crate_name(name) {
184186
help.push_str(&format!(
185187
"\n\
186-
If you need a binary with the name \"{name}\", use a valid package \
188+
help: to name the binary \"{name}\", use a valid package \
187189
name, and set the binary name to be different from the package. \
188190
This can be done by setting the binary filename to `src/bin/{name}.rs` \
189191
or change the name in Cargo.toml with:\n\
@@ -204,22 +206,22 @@ fn check_name(
204206

205207
if restricted_names::is_keyword(name) {
206208
anyhow::bail!(
207-
"the name `{}` cannot be used as a package name, it is a Rust keyword{}",
209+
"invalid package name `{}`: it is a Rust keyword{}",
208210
name,
209211
bin_help()
210212
);
211213
}
212214
if restricted_names::is_conflicting_artifact_name(name) {
213215
if has_bin {
214216
anyhow::bail!(
215-
"the name `{}` cannot be used as a package name, \
217+
"invalid package name `{}`: \
216218
it conflicts with cargo's build directory names{}",
217219
name,
218220
name_help
219221
);
220222
} else {
221223
shell.warn(format!(
222-
"the name `{}` will not support binary \
224+
"package `{}` will not support binary \
223225
executables with that name, \
224226
it conflicts with cargo's build directory names",
225227
name
@@ -228,14 +230,14 @@ fn check_name(
228230
}
229231
if name == "test" {
230232
anyhow::bail!(
231-
"the name `test` cannot be used as a package name, \
233+
"invalid package name `test`: \
232234
it conflicts with Rust's built-in test library{}",
233235
bin_help()
234236
);
235237
}
236238
if ["core", "std", "alloc", "proc_macro", "proc-macro"].contains(&name) {
237239
shell.warn(format!(
238-
"the name `{}` is part of Rust's standard library\n\
240+
"package name `{}` may be confused with the package with that name in Rust's standard library\n\
239241
It is recommended to use a different name to avoid problems.{}",
240242
name,
241243
bin_help()
@@ -244,35 +246,52 @@ fn check_name(
244246
if restricted_names::is_windows_reserved(name) {
245247
if cfg!(windows) {
246248
anyhow::bail!(
247-
"cannot use name `{}`, it is a reserved Windows filename{}",
249+
"invalid package name `{}`: it is a reserved Windows filename{}",
248250
name,
249251
name_help
250252
);
251253
} else {
252254
shell.warn(format!(
253-
"the name `{}` is a reserved Windows filename\n\
255+
"package name `{}` is a reserved Windows filename\n\
254256
This package will not work on Windows platforms.",
255257
name
256258
))?;
257259
}
258260
}
259261
if restricted_names::is_non_ascii_name(name) {
260262
shell.warn(format!(
261-
"the name `{}` contains non-ASCII characters\n\
263+
"invalid package name `{}`: contains non-ASCII characters\n\
262264
Non-ASCII crate names are not supported by Rust.",
263265
name
264266
))?;
265267
}
266268
let name_in_lowercase = name.to_lowercase();
267269
if name != name_in_lowercase {
268270
shell.warn(format!(
269-
"the name `{name}` is not snake_case or kebab-case which is recommended for package names, consider `{name_in_lowercase}`"
271+
"package name `{name}` is not snake_case or kebab-case which is recommended for package names, consider `{name_in_lowercase}`"
270272
))?;
271273
}
272274

273275
Ok(())
274276
}
275277

278+
// Taken from <https://github.com/rust-lang/rust/blob/693f365667a97b24cb40173bc2801eb66ea53020/compiler/rustc_session/src/output.rs#L49-L79>
279+
fn validate_crate_name(name: &str) -> bool {
280+
if name.is_empty() {
281+
return false;
282+
}
283+
284+
for c in name.chars() {
285+
if c.is_alphanumeric() || c == '-' || c == '_' {
286+
continue;
287+
} else {
288+
return false;
289+
}
290+
}
291+
292+
true
293+
}
294+
276295
/// Checks if the path contains any invalid PATH env characters.
277296
fn check_path(path: &Path, shell: &mut Shell) -> CargoResult<()> {
278297
// warn if the path contains characters that will break `env::join_paths`

tests/testsuite/cargo_init/invalid_dir_name/stderr.term.svg

Lines changed: 4 additions & 14 deletions
Loading

tests/testsuite/cargo_init/reserved_name/stderr.term.svg

Lines changed: 12 additions & 10 deletions
Loading

tests/testsuite/new.rs

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,8 @@ fn invalid_characters() {
168168
.with_stderr_data(str![[r#"
169169
[CREATING] binary (application) `foo.rs` package
170170
[ERROR] invalid character `.` in package name: `foo.rs`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)
171-
If you need a package name to not match the directory name, consider using --name flag.
172-
If you need a binary with the name "foo.rs", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/foo.rs.rs` or change the name in Cargo.toml with:
173-
174-
[[bin]]
175-
name = "foo.rs"
176-
path = "src/main.rs"
177-
171+
[NOTE] the directory name is used as the package name
172+
[HELP] to override the package name, pass `--name <pkgname>`
178173
179174
"#]])
180175
.run();
@@ -186,9 +181,10 @@ fn reserved_name() {
186181
.with_status(101)
187182
.with_stderr_data(str![[r#"
188183
[CREATING] binary (application) `test` package
189-
[ERROR] the name `test` cannot be used as a package name, it conflicts with Rust's built-in test library
190-
If you need a package name to not match the directory name, consider using --name flag.
191-
If you need a binary with the name "test", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/test.rs` or change the name in Cargo.toml with:
184+
[ERROR] invalid package name `test`: it conflicts with Rust's built-in test library
185+
[NOTE] the directory name is used as the package name
186+
[HELP] to override the package name, pass `--name <pkgname>`
187+
[HELP] to name the binary "test", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/test.rs` or change the name in Cargo.toml with:
192188
193189
[[bin]]
194190
name = "test"
@@ -205,16 +201,17 @@ fn reserved_binary_name() {
205201
.with_status(101)
206202
.with_stderr_data(str![[r#"
207203
[CREATING] binary (application) `incremental` package
208-
[ERROR] the name `incremental` cannot be used as a package name, it conflicts with cargo's build directory names
209-
If you need a package name to not match the directory name, consider using --name flag.
204+
[ERROR] invalid package name `incremental`: it conflicts with cargo's build directory names
205+
[NOTE] the directory name is used as the package name
206+
[HELP] to override the package name, pass `--name <pkgname>`
210207
211208
"#]])
212209
.run();
213210

214211
cargo_process("new --lib incremental")
215212
.with_stderr_data(str![[r#"
216213
[CREATING] library `incremental` package
217-
[WARNING] the name `incremental` will not support binary executables with that name, it conflicts with cargo's build directory names
214+
[WARNING] package `incremental` will not support binary executables with that name, it conflicts with cargo's build directory names
218215
[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
219216
220217
"#]])
@@ -227,9 +224,10 @@ fn keyword_name() {
227224
.with_status(101)
228225
.with_stderr_data(str![[r#"
229226
[CREATING] binary (application) `pub` package
230-
[ERROR] the name `pub` cannot be used as a package name, it is a Rust keyword
231-
If you need a package name to not match the directory name, consider using --name flag.
232-
If you need a binary with the name "pub", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/pub.rs` or change the name in Cargo.toml with:
227+
[ERROR] invalid package name `pub`: it is a Rust keyword
228+
[NOTE] the directory name is used as the package name
229+
[HELP] to override the package name, pass `--name <pkgname>`
230+
[HELP] to name the binary "pub", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/pub.rs` or change the name in Cargo.toml with:
233231
234232
[[bin]]
235233
name = "pub"
@@ -244,10 +242,11 @@ If you need a binary with the name "pub", use a valid package name, and set the
244242
fn std_name() {
245243
cargo_process("new core").with_stderr_data(str![[r#"
246244
[CREATING] binary (application) `core` package
247-
[WARNING] the name `core` is part of Rust's standard library
245+
[WARNING] package name `core` may be confused with the package with that name in Rust's standard library
248246
It is recommended to use a different name to avoid problems.
249-
If you need a package name to not match the directory name, consider using --name flag.
250-
If you need a binary with the name "core", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/core.rs` or change the name in Cargo.toml with:
247+
[NOTE] the directory name is used as the package name
248+
[HELP] to override the package name, pass `--name <pkgname>`
249+
[HELP] to name the binary "core", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/core.rs` or change the name in Cargo.toml with:
251250
252251
[[bin]]
253252
name = "core"
@@ -369,7 +368,7 @@ fn explicit_invalid_name_not_suggested() {
369368
.with_stderr_data(str![[r#"
370369
[CREATING] binary (application) `10-invalid` package
371370
[ERROR] invalid character `1` in package name: `10-invalid`, the name cannot start with a digit
372-
If you need a binary with the name "10-invalid", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/10-invalid.rs` or change the name in Cargo.toml with:
371+
[HELP] to name the binary "10-invalid", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/10-invalid.rs` or change the name in Cargo.toml with:
373372
374373
[[bin]]
375374
name = "10-invalid"
@@ -441,15 +440,16 @@ fn restricted_windows_name() {
441440
.with_status(101)
442441
.with_stderr_data(str![[r#"
443442
[CREATING] binary (application) `nul` package
444-
[ERROR] cannot use name `nul`, it is a reserved Windows filename
445-
If you need a package name to not match the directory name, consider using --name flag.
443+
[ERROR] invalid package name `nul`: it is a reserved Windows filename
444+
[NOTE] the directory name is used as the package name
445+
[HELP] to override the package name, pass `--name <pkgname>`
446446
447447
"#]])
448448
.run();
449449
} else {
450450
cargo_process("new nul").with_stderr_data(str![[r#"
451451
[CREATING] binary (application) `nul` package
452-
[WARNING] the name `nul` is a reserved Windows filename
452+
[WARNING] package name `nul` is a reserved Windows filename
453453
This package will not work on Windows platforms.
454454
[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
455455
@@ -461,9 +461,9 @@ This package will not work on Windows platforms.
461461
fn non_ascii_name() {
462462
cargo_process("new Привет").with_stderr_data(str![[r#"
463463
[CREATING] binary (application) `Привет` package
464-
[WARNING] the name `Привет` contains non-ASCII characters
464+
[WARNING] invalid package name `Привет`: contains non-ASCII characters
465465
Non-ASCII crate names are not supported by Rust.
466-
[WARNING] the name `Привет` is not snake_case or kebab-case which is recommended for package names, consider `привет`
466+
[WARNING] package name `Привет` is not snake_case or kebab-case which is recommended for package names, consider `привет`
467467
[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
468468
469469
"#]]).run();
@@ -477,8 +477,9 @@ fn non_ascii_name_invalid() {
477477
.with_stderr_data(str![[r#"
478478
[CREATING] binary (application) `ⒶⒷⒸ` package
479479
[ERROR] invalid character `Ⓐ` in package name: `ⒶⒷⒸ`, the first character must be a Unicode XID start character (most letters or `_`)
480-
If you need a package name to not match the directory name, consider using --name flag.
481-
If you need a binary with the name "ⒶⒷⒸ", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/ⒶⒷⒸ.rs` or change the name in Cargo.toml with:
480+
[NOTE] the directory name is used as the package name
481+
[HELP] to override the package name, pass `--name <pkgname>`
482+
[HELP] to name the binary "ⒶⒷⒸ", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/ⒶⒷⒸ.rs` or change the name in Cargo.toml with:
482483
483484
[[bin]]
484485
name = "ⒶⒷⒸ"
@@ -493,8 +494,9 @@ If you need a binary with the name "ⒶⒷⒸ", use a valid package name, and se
493494
.with_stderr_data(str![[r#"
494495
[CREATING] binary (application) `a¼` package
495496
[ERROR] invalid character `¼` in package name: `a¼`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)
496-
If you need a package name to not match the directory name, consider using --name flag.
497-
If you need a binary with the name "a¼", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/a¼.rs` or change the name in Cargo.toml with:
497+
[NOTE] the directory name is used as the package name
498+
[HELP] to override the package name, pass `--name <pkgname>`
499+
[HELP] to name the binary "a¼", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/a¼.rs` or change the name in Cargo.toml with:
498500
499501
[[bin]]
500502
name = "a¼"
@@ -510,7 +512,7 @@ fn non_snake_case_name() {
510512
cargo_process("new UPPERcase_name")
511513
.with_stderr_data(str![[r#"
512514
[CREATING] binary (application) `UPPERcase_name` package
513-
[WARNING] the name `UPPERcase_name` is not snake_case or kebab-case which is recommended for package names, consider `uppercase_name`
515+
[WARNING] package name `UPPERcase_name` is not snake_case or kebab-case which is recommended for package names, consider `uppercase_name`
514516
[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
515517
516518
"#]])

0 commit comments

Comments
 (0)