Skip to content

Commit e426186

Browse files
committed
feat: Add "-Zpublic-dependency" for public-dependency feature
1 parent 98079d9 commit e426186

File tree

7 files changed

+190
-23
lines changed

7 files changed

+190
-23
lines changed

src/cargo/core/compiler/mod.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,15 +1506,14 @@ pub fn extern_args(
15061506
|dep: &UnitDep, extern_crate_name: InternedString, noprelude: bool| -> CargoResult<()> {
15071507
let mut value = OsString::new();
15081508
let mut opts = Vec::new();
1509-
if unit
1509+
let is_public_dependency_enabled = unit
15101510
.pkg
15111511
.manifest()
15121512
.unstable_features()
15131513
.require(Feature::public_dependency())
15141514
.is_ok()
1515-
&& !dep.public
1516-
&& unit.target.is_lib()
1517-
{
1515+
|| build_runner.bcx.gctx.cli_unstable().public_dependency;
1516+
if !dep.public && unit.target.is_lib() && is_public_dependency_enabled {
15181517
opts.push("priv");
15191518
*unstable_opts = true;
15201519
}

src/cargo/core/features.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,7 @@ unstable_cli_options!(
765765
panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"),
766766
precise_pre_release: bool = ("Enable pre-release versions to be selected with `update --precise`"),
767767
profile_rustflags: bool = ("Enable the `rustflags` option in profiles in .cargo/config.toml file"),
768+
public_dependency: bool = ("Respect a dependency's `public` field in Cargo.toml to control public/private dependencies"),
768769
publish_timeout: bool = ("Enable the `publish.timeout` key in .cargo/config.toml file"),
769770
rustdoc_map: bool = ("Allow passing external documentation mappings to rustdoc"),
770771
rustdoc_scrape_examples: bool = ("Allows Rustdoc to scrape code examples from reverse-dependencies"),
@@ -1141,6 +1142,7 @@ impl CliUnstable {
11411142
"mtime-on-use" => self.mtime_on_use = parse_empty(k, v)?,
11421143
"no-index-update" => self.no_index_update = parse_empty(k, v)?,
11431144
"panic-abort-tests" => self.panic_abort_tests = parse_empty(k, v)?,
1145+
"public-dependency" => self.public_dependency = parse_empty(k, v)?,
11441146
"profile-rustflags" => self.profile_rustflags = parse_empty(k, v)?,
11451147
"precise-pre-release" => self.precise_pre_release = parse_empty(k, v)?,
11461148
"trim-paths" => self.trim_paths = parse_empty(k, v)?,

src/cargo/ops/cargo_package.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,7 @@ fn run_verify(
911911
.unstable_features()
912912
.require(Feature::public_dependency())
913913
.is_ok()
914+
|| ws.gctx().cli_unstable().public_dependency
914915
{
915916
// FIXME: Turn this on at some point in the future
916917
//Some(vec!["-D exported_private_dependencies".to_string()])

src/cargo/util/toml/mod.rs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,28 @@ pub fn to_real_manifest(
727727
v.unused_keys(),
728728
manifest_gctx.warnings,
729729
);
730+
let mut resolved = resolved;
731+
732+
if let manifest::TomlDependency::Detailed(ref mut d) = resolved {
733+
if d.public.is_some() {
734+
if matches!(dep.kind(), DepKind::Normal) {
735+
if !manifest_gctx
736+
.features
737+
.require(Feature::public_dependency())
738+
.is_ok()
739+
&& !manifest_gctx.gctx.cli_unstable().public_dependency
740+
{
741+
d.public = None;
742+
manifest_gctx.warnings.push(format!(
743+
"Ignoring `public` on dependency {name}. Pass `-Zpublic-dependency` to enable support for it", name = &dep.name_in_toml()
744+
))
745+
}
746+
} else {
747+
d.public = None;
748+
}
749+
}
750+
}
751+
730752
manifest_gctx.deps.push(dep);
731753
deps.insert(
732754
n.clone(),
@@ -1992,15 +2014,24 @@ fn detailed_dep_to_dependency<P: ResolveToPath + Clone>(
19922014
}
19932015

19942016
if let Some(p) = orig.public {
1995-
manifest_gctx
1996-
.features
1997-
.require(Feature::public_dependency())?;
2017+
let public_feature = manifest_gctx.features.require(Feature::public_dependency());
2018+
let with_z_public = manifest_gctx.gctx.cli_unstable().public_dependency;
2019+
let with_public_feature = public_feature.is_ok();
2020+
if !with_public_feature && (!with_z_public && !manifest_gctx.gctx.nightly_features_allowed)
2021+
{
2022+
public_feature?;
2023+
}
19982024

19992025
if dep.kind() != DepKind::Normal {
2000-
bail!("'public' specifier can only be used on regular dependencies, not {:?} dependencies", dep.kind());
2026+
match (with_public_feature, with_z_public) {
2027+
(true, _) => bail!("'public' specifier can only be used on regular dependencies, not {:?} dependencies", dep.kind()),
2028+
(_, true) => bail!("'public' specifier can only be used on regular dependencies, not {:?} dependencies", dep.kind()),
2029+
// If public feature isn't enabled in nightly, we instead warn that.
2030+
(false, false) => manifest_gctx.warnings.push(format!("'public' specifier can only be used on regular dependencies, not {:?} dependencies", dep.kind())),
2031+
}
2032+
} else {
2033+
dep.set_public(p);
20012034
}
2002-
2003-
dep.set_public(p);
20042035
}
20052036

20062037
if let (Some(artifact), is_lib, target) = (

tests/build-std/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ fn enable_build_std(e: &mut Execs, arg: Option<&str>) {
3333
Some(s) => format!("-Zbuild-std={}", s),
3434
None => "-Zbuild-std".to_string(),
3535
};
36-
e.arg(arg);
36+
e.arg(arg).arg("-Zpublic-dependency");
3737
e.masquerade_as_nightly_cargo(&["build-std"]);
3838
}
3939

tests/testsuite/cargo/z_help/stdout.log

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Available unstable (nightly-only) flags:
2525
-Z panic-abort-tests Enable support to run tests with -Cpanic=abort
2626
-Z precise-pre-release Enable pre-release versions to be selected with `update --precise`
2727
-Z profile-rustflags Enable the `rustflags` option in profiles in .cargo/config.toml file
28+
-Z public-dependency Respect a dependency's `public` field in Cargo.toml to control public/private dependencies
2829
-Z publish-timeout Enable the `publish.timeout` key in .cargo/config.toml file
2930
-Z rustdoc-map Allow passing external documentation mappings to rustdoc
3031
-Z rustdoc-scrape-examples Allows Rustdoc to scrape code examples from reverse-dependencies

tests/testsuite/pub_priv.rs

Lines changed: 145 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -136,20 +136,15 @@ fn requires_feature() {
136136

137137
p.cargo("check --message-format=short")
138138
.masquerade_as_nightly_cargo(&["public-dependency"])
139-
.with_status(101)
140139
.with_stderr(
141140
"\
142-
error: failed to parse manifest at `[..]`
143-
144-
Caused by:
145-
feature `public-dependency` is required
146-
147-
The package requires the Cargo feature called `public-dependency`, \
148-
but that feature is not stabilized in this version of Cargo (1.[..]).
149-
Consider adding `cargo-features = [\"public-dependency\"]` to the top of Cargo.toml \
150-
(above the [package] table) to tell Cargo you are opting in to use this unstable feature.
151-
See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#public-dependency \
152-
for more information about the status of this feature.
141+
[WARNING] Ignoring `public` on dependency pub_dep. Pass `-Zpublic-dependency` to enable support for it
142+
[UPDATING] `[..]` index
143+
[DOWNLOADING] crates ...
144+
[DOWNLOADED] pub_dep v0.1.0 ([..])
145+
[CHECKING] pub_dep v0.1.0
146+
[CHECKING] foo v0.0.1 ([CWD])
147+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]
153148
",
154149
)
155150
.run()
@@ -198,6 +193,45 @@ Caused by:
198193
.run()
199194
}
200195

196+
#[cargo_test]
197+
fn pub_dev_dependency_without_feature() {
198+
Package::new("pub_dep", "0.1.0")
199+
.file("src/lib.rs", "pub struct FromPub;")
200+
.publish();
201+
202+
let p = project()
203+
.file(
204+
"Cargo.toml",
205+
r#"
206+
[package]
207+
name = "foo"
208+
version = "0.0.1"
209+
210+
[dev-dependencies]
211+
pub_dep = {version = "0.1.0", public = true}
212+
"#,
213+
)
214+
.file(
215+
"tests/mod.rs",
216+
"
217+
extern crate pub_dep;
218+
pub fn use_pub(_: pub_dep::FromPub) {}
219+
",
220+
)
221+
.build();
222+
223+
p.cargo("check --message-format=short")
224+
.masquerade_as_nightly_cargo(&["public-dependency"])
225+
.with_stderr(
226+
"\
227+
[WARNING] 'public' specifier can only be used on regular dependencies, not Development dependencies
228+
[UPDATING] `[..]` index
229+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]
230+
",
231+
)
232+
.run()
233+
}
234+
201235
#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")]
202236
fn workspace_pub_disallowed() {
203237
Package::new("foo1", "0.1.0")
@@ -534,3 +568,102 @@ fn publish_package_with_public_dependency() {
534568
)
535569
.run()
536570
}
571+
572+
#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")]
573+
fn verify_mix_cargo_feature_z() {
574+
Package::new("dep", "0.1.0")
575+
.file("src/lib.rs", "pub struct FromDep;")
576+
.publish();
577+
Package::new("priv_dep", "0.1.0")
578+
.file("src/lib.rs", "pub struct FromPriv;")
579+
.publish();
580+
Package::new("pub_dep", "0.1.0")
581+
.file("src/lib.rs", "pub struct FromPub;")
582+
.publish();
583+
let p = project()
584+
.file(
585+
"Cargo.toml",
586+
r#"
587+
cargo-features = ["public-dependency"]
588+
[package]
589+
name = "foo"
590+
version = "0.0.1"
591+
592+
[dependencies]
593+
dep = "0.1.0"
594+
priv_dep = {version = "0.1.0", public = false}
595+
pub_dep = {version = "0.1.0", public = true}
596+
"#,
597+
)
598+
.file(
599+
"src/lib.rs",
600+
"
601+
extern crate dep;
602+
extern crate priv_dep;
603+
extern crate pub_dep;
604+
pub fn use_dep(_: dep::FromDep) {}
605+
pub fn use_priv(_: priv_dep::FromPriv) {}
606+
pub fn use_pub(_: pub_dep::FromPub) {}
607+
",
608+
)
609+
.build();
610+
611+
p.cargo("check -Zpublic-dependency --message-format=short")
612+
.masquerade_as_nightly_cargo(&["public-dependency"])
613+
.with_stderr_contains(
614+
"\
615+
src/lib.rs:5:13: warning: type `FromDep` from private dependency 'dep' in public interface
616+
src/lib.rs:6:13: warning: type `FromPriv` from private dependency 'priv_dep' in public interface
617+
",
618+
)
619+
.run();
620+
}
621+
622+
#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")]
623+
fn verify_z_public_dependency() {
624+
Package::new("dep", "0.1.0")
625+
.file("src/lib.rs", "pub struct FromDep;")
626+
.publish();
627+
Package::new("priv_dep", "0.1.0")
628+
.file("src/lib.rs", "pub struct FromPriv;")
629+
.publish();
630+
Package::new("pub_dep", "0.1.0")
631+
.file("src/lib.rs", "pub struct FromPub;")
632+
.publish();
633+
let p = project()
634+
.file(
635+
"Cargo.toml",
636+
r#"
637+
[package]
638+
name = "foo"
639+
version = "0.0.1"
640+
641+
[dependencies]
642+
dep = "0.1.0"
643+
priv_dep = {version = "0.1.0", public = false}
644+
pub_dep = {version = "0.1.0", public = true}
645+
"#,
646+
)
647+
.file(
648+
"src/lib.rs",
649+
"
650+
extern crate dep;
651+
extern crate priv_dep;
652+
extern crate pub_dep;
653+
pub fn use_dep(_: dep::FromDep) {}
654+
pub fn use_priv(_: priv_dep::FromPriv) {}
655+
pub fn use_pub(_: pub_dep::FromPub) {}
656+
",
657+
)
658+
.build();
659+
660+
p.cargo("check -Zpublic-dependency --message-format=short")
661+
.masquerade_as_nightly_cargo(&["public-dependency"])
662+
.with_stderr_contains(
663+
"\
664+
src/lib.rs:5:13: warning: type `FromDep` from private dependency 'dep' in public interface
665+
src/lib.rs:6:13: warning: type `FromPriv` from private dependency 'priv_dep' in public interface
666+
",
667+
)
668+
.run();
669+
}

0 commit comments

Comments
 (0)