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

Warning on conflicting keys #10316

Merged
merged 8 commits into from
Mar 10, 2022
46 changes: 46 additions & 0 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@ pub fn parse_document(
.map_err(|e| anyhow::Error::from(e).context("could not parse input as TOML"))
}

/// Warn about paths that have been deprecated and may conflict.
fn warn_on_deprecated(new_path: &str, name: &str, kind: &str, warnings: &mut Vec<String>) {
let old_path = new_path.replace("-", "_");
warnings.push(format!(
"conflicting between `{new_path}` and `{old_path}` in the `{name}` {kind}.\n
`{old_path}` is ignored and not recommended for use in the future"
))
}

type TomlLibTarget = TomlTarget;
type TomlBinTarget = TomlTarget;
type TomlExampleTarget = TomlTarget;
Expand Down Expand Up @@ -1264,11 +1273,17 @@ impl TomlManifest {

// Collect the dependencies.
process_dependencies(&mut cx, me.dependencies.as_ref(), None)?;
if me.dev_dependencies.is_some() && me.dev_dependencies2.is_some() {
warn_on_deprecated("dev-dependencies", package_name, "package", cx.warnings);
}
let dev_deps = me
.dev_dependencies
.as_ref()
.or_else(|| me.dev_dependencies2.as_ref());
process_dependencies(&mut cx, dev_deps, Some(DepKind::Development))?;
if me.build_dependencies.is_some() && me.build_dependencies2.is_some() {
warn_on_deprecated("build-dependencies", package_name, "package", cx.warnings);
}
let build_deps = me
.build_dependencies
.as_ref()
Expand All @@ -1282,11 +1297,17 @@ impl TomlManifest {
Some(platform)
};
process_dependencies(&mut cx, platform.dependencies.as_ref(), None)?;
if platform.build_dependencies.is_some() && platform.build_dependencies2.is_some() {
warn_on_deprecated("build-dependencies", name, "platform target", cx.warnings);
}
let build_deps = platform
.build_dependencies
.as_ref()
.or_else(|| platform.build_dependencies2.as_ref());
process_dependencies(&mut cx, build_deps, Some(DepKind::Build))?;
if platform.dev_dependencies.is_some() && platform.dev_dependencies2.is_some() {
warn_on_deprecated("dev-dependencies", name, "platform target", cx.warnings);
}
let dev_deps = platform
.dev_dependencies
.as_ref()
Expand Down Expand Up @@ -1908,6 +1929,9 @@ impl<P: ResolveToPath> DetailedTomlDependency<P> {

let version = self.version.as_deref();
let mut dep = Dependency::parse(pkg_name, version, new_source_id)?;
if self.default_features.is_some() && self.default_features2.is_some() {
warn_on_deprecated("default-features", name_in_toml, "dependency", cx.warnings);
}
dep.set_features(self.features.iter().flatten())
.set_default_features(
self.default_features
Expand Down Expand Up @@ -2057,6 +2081,17 @@ impl TomlTarget {
}
}

fn validate_proc_macro(&self, warnings: &mut Vec<String>) {
if self.proc_macro_raw.is_some() && self.proc_macro_raw2.is_some() {
warn_on_deprecated(
"proc-macro",
self.name().as_str(),
"library target",
warnings,
);
}
}

fn proc_macro(&self) -> Option<bool> {
self.proc_macro_raw.or(self.proc_macro_raw2).or_else(|| {
if let Some(types) = self.crate_types() {
Expand All @@ -2068,6 +2103,17 @@ impl TomlTarget {
})
}

fn validate_crate_types(&self, target_kind_human: &str, warnings: &mut Vec<String>) {
if self.crate_type.is_some() && self.crate_type2.is_some() {
warn_on_deprecated(
"crate-type",
self.name().as_str(),
format!("{target_kind_human} target").as_str(),
warnings,
);
}
}

fn crate_types(&self) -> Option<&Vec<String>> {
self.crate_type
.as_ref()
Expand Down
3 changes: 3 additions & 0 deletions src/cargo/util/toml/targets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ fn clean_lib(
Some(ref lib) => lib,
None => return Ok(None),
};
lib.validate_proc_macro(warnings);
lib.validate_crate_types("library", warnings);

validate_target_name(lib, "library", "lib", warnings)?;

Expand Down Expand Up @@ -398,6 +400,7 @@ fn clean_examples(

let mut result = Vec::new();
for (path, toml) in targets {
toml.validate_crate_types("example", warnings);
let crate_types = match toml.crate_types() {
Some(kinds) => kinds.iter().map(|s| s.into()).collect(),
None => Vec::new(),
Expand Down
229 changes: 229 additions & 0 deletions tests/testsuite/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1676,6 +1676,153 @@ Caused by:
.run();
}

#[cargo_test]
fn dev_dependencies_conflicting_warning() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
edition = "2018"

[dev-dependencies]
a = {path = "a"}
[dev_dependencies]
a = {path = "a"}
"#,
)
.file("src/lib.rs", "")
.file(
"a/Cargo.toml",
r#"
[package]
name = "a"
version = "0.0.1"
"#,
)
.file("a/src/lib.rs", "")
.build();
p.cargo("build")
.with_stderr_contains(
"[WARNING] conflicting between `dev-dependencies` and `dev_dependencies` in the `foo` package.\n
`dev_dependencies` is ignored and not recommended for use in the future"
)
.run();
}

#[cargo_test]
fn build_dependencies_conflicting_warning() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
edition = "2018"

[build-dependencies]
a = {path = "a"}
[build_dependencies]
a = {path = "a"}
"#,
)
.file("src/lib.rs", "")
.file(
"a/Cargo.toml",
r#"
[package]
name = "a"
version = "0.0.1"
"#,
)
.file("a/src/lib.rs", "")
.build();
p.cargo("build")
.with_stderr_contains(
"[WARNING] conflicting between `build-dependencies` and `build_dependencies` in the `foo` package.\n
`build_dependencies` is ignored and not recommended for use in the future"
)
.run();
}

#[cargo_test]
fn lib_crate_types_conflicting_warning() {
let p = project()
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.5.0"
authors = ["wycats@example.com"]

[lib]
name = "foo"
crate-type = ["rlib", "dylib"]
crate_type = ["staticlib", "dylib"]
"#,
)
.file("src/lib.rs", "pub fn foo() {}")
.build();
p.cargo("build")
.with_stderr_contains(
"[WARNING] conflicting between `crate-type` and `crate_type` in the `foo` library target.\n
`crate_type` is ignored and not recommended for use in the future",
)
.run();
}

#[cargo_test]
fn examples_crate_types_conflicting_warning() {
let p = project()
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.5.0"
authors = ["wycats@example.com"]

[[example]]
name = "ex"
path = "examples/ex.rs"
crate-type = ["rlib", "dylib"]
crate_type = ["proc_macro"]
[[example]]
name = "goodbye"
path = "examples/ex-goodbye.rs"
crate-type = ["rlib", "dylib"]
crate_type = ["rlib", "staticlib"]
"#,
)
.file("src/lib.rs", "")
.file(
"examples/ex.rs",
r#"
fn main() { println!("ex"); }
"#,
)
.file(
"examples/ex-goodbye.rs",
r#"
fn main() { println!("goodbye"); }
"#,
Rustin170506 marked this conversation as resolved.
Show resolved Hide resolved
)
.build();
p.cargo("build")
.with_stderr_contains(
"\
[WARNING] conflicting between `crate-type` and `crate_type` in the `ex` example target.\n
`crate_type` is ignored and not recommended for use in the future
[WARNING] conflicting between `crate-type` and `crate_type` in the `goodbye` example target.\n
`crate_type` is ignored and not recommended for use in the future",
)
.run();
}

#[cargo_test]
fn self_dependency() {
let p = project()
Expand Down Expand Up @@ -2841,6 +2988,88 @@ fn cargo_platform_specific_dependency() {
p.cargo("test").run();
}

#[cargo_test]
fn cargo_platform_specific_dependency_build_dependencies_conflicting_warning() {
let host = rustc_host();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[project]
name = "foo"
version = "0.5.0"
authors = ["wycats@example.com"]
build = "build.rs"

[target.{host}.build-dependencies]
build = {{ path = "build" }}
[target.{host}.build_dependencies]
build = {{ path = "build" }}
"#,
host = host
),
)
.file("src/main.rs", "fn main() { }")
.file(
"build.rs",
"extern crate build; fn main() { build::build(); }",
)
.file("build/Cargo.toml", &basic_manifest("build", "0.5.0"))
.file("build/src/lib.rs", "pub fn build() {}")
.build();

p.cargo("build")
.with_stderr_contains(
format!("[WARNING] conflicting between `build-dependencies` and `build_dependencies` in the `{}` platform target.\n
`build_dependencies` is ignored and not recommended for use in the future", host)
)
.run();

assert!(p.bin("foo").is_file());
}

#[cargo_test]
fn cargo_platform_specific_dependency_dev_dependencies_conflicting_warning() {
let host = rustc_host();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[project]
name = "foo"
version = "0.5.0"
authors = ["wycats@example.com"]

[target.{host}.dev-dependencies]
dev = {{ path = "dev" }}
[target.{host}.dev_dependencies]
dev = {{ path = "dev" }}
"#,
host = host
),
)
.file("src/main.rs", "fn main() { }")
.file(
"tests/foo.rs",
"extern crate dev; #[test] fn foo() { dev::dev() }",
)
.file("dev/Cargo.toml", &basic_manifest("dev", "0.5.0"))
.file("dev/src/lib.rs", "pub fn dev() {}")
.build();

p.cargo("build")
.with_stderr_contains(
format!("[WARNING] conflicting between `dev-dependencies` and `dev_dependencies` in the `{}` platform target.\n
`dev_dependencies` is ignored and not recommended for use in the future", host)
)
.run();

assert!(p.bin("foo").is_file());
p.cargo("test").run();
}

#[cargo_test]
fn bad_platform_specific_dependency() {
let p = project()
Expand Down
Loading