Skip to content

Commit

Permalink
feat: Add "-Zpublic-denpendency" for public-dependency feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
linyihai committed Jan 18, 2024
1 parent c061bfb commit 2fff2fd
Show file tree
Hide file tree
Showing 30 changed files with 199 additions and 210 deletions.
12 changes: 2 additions & 10 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ use crate::core::compiler::future_incompat::FutureIncompatReport;
pub use crate::core::compiler::unit::{Unit, UnitInterner};
use crate::core::manifest::TargetSourcePath;
use crate::core::profiles::{PanicStrategy, Profile, StripInner};
use crate::core::{Feature, PackageId, Target, Verbosity};
use crate::core::{PackageId, Target, Verbosity};
use crate::util::errors::{CargoResult, VerboseError};
use crate::util::interning::InternedString;
use crate::util::machine_message::{self, Message};
Expand Down Expand Up @@ -1437,15 +1437,7 @@ pub fn extern_args(
|dep: &UnitDep, extern_crate_name: InternedString, noprelude: bool| -> CargoResult<()> {
let mut value = OsString::new();
let mut opts = Vec::new();
if unit
.pkg
.manifest()
.unstable_features()
.require(Feature::public_dependency())
.is_ok()
&& !dep.public
&& unit.target.is_lib()
{
if !dep.public && unit.target.is_lib() {
opts.push("priv");
*unstable_opts = true;
}
Expand Down
2 changes: 2 additions & 0 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,7 @@ unstable_cli_options!(
panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"),
precise_pre_release: bool = ("Enable pre-release versions to be selected with `update --precise`"),
profile_rustflags: bool = ("Enable the `rustflags` option in profiles in .cargo/config.toml file"),
public_dependency: bool = ("Enable public-dependency to allow marking dependencies as public/private"),
publish_timeout: bool = ("Enable the `publish.timeout` key in .cargo/config.toml file"),
rustdoc_map: bool = ("Allow passing external documentation mappings to rustdoc"),
rustdoc_scrape_examples: bool = ("Allows Rustdoc to scrape code examples from reverse-dependencies"),
Expand Down Expand Up @@ -1140,6 +1141,7 @@ impl CliUnstable {
"mtime-on-use" => self.mtime_on_use = parse_empty(k, v)?,
"no-index-update" => self.no_index_update = parse_empty(k, v)?,
"panic-abort-tests" => self.panic_abort_tests = parse_empty(k, v)?,
"public-dependency" => self.public_dependency = parse_empty(k, v)?,
"profile-rustflags" => self.profile_rustflags = parse_empty(k, v)?,
"precise-pre-release" => self.precise_pre_release = parse_empty(k, v)?,
"trim-paths" => self.trim_paths = parse_empty(k, v)?,
Expand Down
1 change: 0 additions & 1 deletion src/cargo/core/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,6 @@ impl<'cfg> Workspace<'cfg> {
// NOTE: Since we use ConfigRelativePath, this root isn't used as
// any relative paths are resolved before they'd be joined with root.
Path::new("unused-relative-path"),
self.unstable_features(),
/* kind */ None,
)
})
Expand Down
17 changes: 2 additions & 15 deletions src/cargo/ops/cargo_package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use crate::core::compiler::{BuildConfig, CompileMode, DefaultExecutor, Executor}
use crate::core::manifest::Target;
use crate::core::resolver::CliFeatures;
use crate::core::{registry::PackageRegistry, resolver::HasDevUnits};
use crate::core::{Feature, Shell, Verbosity, Workspace};
use crate::core::{Package, PackageId, PackageSet, Resolve, SourceId};
use crate::core::{Shell, Verbosity, Workspace};
use crate::sources::PathSource;
use crate::util::cache_lock::CacheLockMode;
use crate::util::config::JobsConfig;
Expand Down Expand Up @@ -910,20 +910,7 @@ fn run_verify(
let new_pkg = src.root_package()?;
let pkg_fingerprint = hash_all(&dst)?;
let ws = Workspace::ephemeral(new_pkg, config, None, true)?;

let rustc_args = if pkg
.manifest()
.unstable_features()
.require(Feature::public_dependency())
.is_ok()
{
// FIXME: Turn this on at some point in the future
//Some(vec!["-D exported_private_dependencies".to_string()])
Some(vec![])
} else {
None
};

let rustc_args = Some(vec![]);
let exec: Arc<dyn Executor> = Arc::new(DefaultExecutor);
ops::compile_with_exec(
&ws,
Expand Down
140 changes: 79 additions & 61 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use crate::AlreadyPrintedError;
use anyhow::{anyhow, bail, Context as _};
use cargo_platform::Platform;
use cargo_util::paths;
use cargo_util_schemas::manifest;
use cargo_util_schemas::manifest::RustVersion;
use cargo_util_schemas::manifest::{self, InheritableDependency};
use cargo_util_schemas::manifest::{RustVersion, TomlDependency};
use itertools::Itertools;
use lazycell::LazyCell;
use pathdiff::diff_paths;
Expand Down Expand Up @@ -105,61 +105,62 @@ fn read_manifest_from_str(

let mut unused = BTreeSet::new();
let deserializer = toml::de::Deserializer::new(contents);
let manifest: manifest::TomlManifest = match serde_ignored::deserialize(deserializer, |path| {
let mut key = String::new();
stringify(&mut key, &path);
unused.insert(key);
}) {
Ok(manifest) => manifest,
Err(e) => {
let Some(span) = e.span() else {
return Err(e.into());
};
let mut manifest: manifest::TomlManifest =
match serde_ignored::deserialize(deserializer, |path| {
let mut key = String::new();
stringify(&mut key, &path);
unused.insert(key);
}) {
Ok(manifest) => manifest,
Err(e) => {
let Some(span) = e.span() else {
return Err(e.into());
};

let (line_num, column) = translate_position(&contents, span.start);
let source_start = contents[0..span.start]
.rfind('\n')
.map(|s| s + 1)
.unwrap_or(0);
let source_end = contents[span.end - 1..]
.find('\n')
.map(|s| s + span.end)
.unwrap_or(contents.len());
let source = &contents[source_start..source_end];
// Make sure we don't try to highlight past the end of the line,
// but also make sure we are highlighting at least one character
let highlight_end = (column + contents[span].chars().count())
.min(source.len())
.max(column + 1);
// Get the path to the manifest, relative to the cwd
let manifest_path = diff_paths(manifest_file, config.cwd())
.unwrap_or_else(|| manifest_file.to_path_buf())
.display()
.to_string();
let snippet = Snippet {
title: Some(Annotation {
id: None,
label: Some(e.message()),
annotation_type: AnnotationType::Error,
}),
footer: vec![],
slices: vec![Slice {
source: &source,
line_start: line_num + 1,
origin: Some(manifest_path.as_str()),
annotations: vec![SourceAnnotation {
range: (column, highlight_end),
label: "",
let (line_num, column) = translate_position(&contents, span.start);
let source_start = contents[0..span.start]
.rfind('\n')
.map(|s| s + 1)
.unwrap_or(0);
let source_end = contents[span.end - 1..]
.find('\n')
.map(|s| s + span.end)
.unwrap_or(contents.len());
let source = &contents[source_start..source_end];
// Make sure we don't try to highlight past the end of the line,
// but also make sure we are highlighting at least one character
let highlight_end = (column + contents[span].chars().count())
.min(source.len())
.max(column + 1);
// Get the path to the manifest, relative to the cwd
let manifest_path = diff_paths(manifest_file, config.cwd())
.unwrap_or_else(|| manifest_file.to_path_buf())
.display()
.to_string();
let snippet = Snippet {
title: Some(Annotation {
id: None,
label: Some(e.message()),
annotation_type: AnnotationType::Error,
}),
footer: vec![],
slices: vec![Slice {
source: &source,
line_start: line_num + 1,
origin: Some(manifest_path.as_str()),
annotations: vec![SourceAnnotation {
range: (column, highlight_end),
label: "",
annotation_type: AnnotationType::Error,
}],
fold: false,
}],
fold: false,
}],
};
let renderer = Renderer::styled();
writeln!(config.shell().err(), "{}", renderer.render(snippet))?;
return Err(AlreadyPrintedError::new(e.into()).into());
}
};
};
let renderer = Renderer::styled();
writeln!(config.shell().err(), "{}", renderer.render(snippet))?;
return Err(AlreadyPrintedError::new(e.into()).into());
}
};
let add_unused = |warnings: &mut Warnings| {
for key in unused {
warnings.add_warning(format!("unused manifest key: {}", key));
Expand All @@ -183,10 +184,33 @@ fn read_manifest_from_str(
}
}
}

let mut public_deps_without_z = BTreeSet::new();
if let Some(deps) = &mut manifest.dependencies {
for (name, dep) in deps {
if let InheritableDependency::Value(toml_dep) = dep {
if toml_dep.is_public() && !config.cli_unstable().public_dependency {
if let TomlDependency::Detailed(d) = toml_dep {
d.public = Some(false)
}
public_deps_without_z.insert(name.clone());
}
}
}
}
let public_warn = |warnings: &mut Warnings| {
for name in public_deps_without_z {
warnings.add_warning(format!(
"{name} is public, pass `-Zpublic-dependency` to enable support for it",
))
}
};

return if manifest.project.is_some() || manifest.package.is_some() {
let (mut manifest, paths) =
to_real_manifest(manifest, embedded, source_id, package_root, config)?;
add_unused(manifest.warnings_mut());
public_warn(manifest.warnings_mut());
if manifest.targets().iter().all(|t| t.is_custom_build()) {
bail!(
"no targets specified in the manifest\n\
Expand All @@ -198,6 +222,7 @@ fn read_manifest_from_str(
} else {
let (mut m, paths) = to_virtual_manifest(manifest, source_id, package_root, config)?;
add_unused(m.warnings_mut());
public_warn(m.warnings_mut());
Ok((EitherManifest::Virtual(m), paths))
};

Expand Down Expand Up @@ -678,7 +703,6 @@ pub fn to_real_manifest(
nested_paths: &mut nested_paths,
config,
warnings: &mut warnings,
features: &features,
platform: None,
root: package_root,
};
Expand Down Expand Up @@ -1153,7 +1177,6 @@ fn to_virtual_manifest(
config,
warnings: &mut warnings,
platform: None,
features: &features,
root,
};
(replace(&me, &mut cx)?, patch(&me, &mut cx)?)
Expand Down Expand Up @@ -1302,7 +1325,6 @@ struct Context<'a, 'b> {
warnings: &'a mut Vec<String>,
platform: Option<Platform>,
root: &'a Path,
features: &'a Features,
}

fn verify_lints(lints: Option<manifest::TomlLints>) -> CargoResult<Option<manifest::TomlLints>> {
Expand Down Expand Up @@ -1709,7 +1731,6 @@ pub(crate) fn to_dependency<P: ResolveToPath + Clone>(
warnings: &mut Vec<String>,
platform: Option<Platform>,
root: &Path,
features: &Features,
kind: Option<DepKind>,
) -> CargoResult<Dependency> {
dep_to_dependency(
Expand All @@ -1723,7 +1744,6 @@ pub(crate) fn to_dependency<P: ResolveToPath + Clone>(
warnings,
platform,
root,
features,
},
kind,
)
Expand Down Expand Up @@ -1944,8 +1964,6 @@ fn detailed_dep_to_dependency<P: ResolveToPath + Clone>(
}

if let Some(p) = orig.public {
cx.features.require(Feature::public_dependency())?;

if dep.kind() != DepKind::Normal {
bail!("'public' specifier can only be used on regular dependencies, not {:?} dependencies", dep.kind());
}
Expand Down
4 changes: 1 addition & 3 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,11 +296,9 @@ The 'public-dependency' feature allows marking dependencies as 'public'
or 'private'. When this feature is enabled, additional information is passed to rustc to allow
the 'exported_private_dependencies' lint to function properly.

This requires the appropriate key to be set in `cargo-features`:
Pass `-Zpublic-dependency` to cargo to enable support for it.

```toml
cargo-features = ["public-dependency"]

[dependencies]
my_dep = { version = "1.2.3", public = true }
private_dep = "2.0.0" # Will be 'private' by default
Expand Down
6 changes: 5 additions & 1 deletion tests/testsuite/artifact_dep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2573,6 +2573,10 @@ fn with_assumed_host_target_and_optional_build_dep() {
.run();
}

// Since public-dependency had switched to non-blocking feature gate, (See https://github.com/rust-lang/cargo/issues/13308)
// this test case will warn "trait `c::Trait` from private dependency 'c' in public interface".
// The weird sutuation is that the warning "warning: `a` (lib) generated 1 warning (1 duplicate)" will appear randomly.
// Add #[allow(exported_private_dependencies)] to suppress it.
#[cargo_test]
fn decouple_same_target_transitive_dep_from_artifact_dep() {
// See https://github.com/rust-lang/cargo/issues/11463
Expand Down Expand Up @@ -2636,7 +2640,7 @@ fn decouple_same_target_transitive_dep_from_artifact_dep() {
"a/src/lib.rs",
r#"
use b::Trait as _;
#[allow(exported_private_dependencies)]
pub fn use_b_trait(x: &impl c::Trait) {
x.b();
}
Expand Down
11 changes: 7 additions & 4 deletions tests/testsuite/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1439,7 +1439,8 @@ fn cargo_default_env_metadata_env_var() {
-C extra-filename=[..] \
--out-dir [..] \
-L dependency=[CWD]/target/debug/deps \
--extern bar=[CWD]/target/debug/deps/{prefix}bar{suffix}`
--extern 'priv:bar=[CWD]/target/debug/deps/{prefix}bar{suffix}' \
-Z unstable-options`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
prefix = env::consts::DLL_PREFIX,
suffix = env::consts::DLL_SUFFIX,
Expand Down Expand Up @@ -1467,7 +1468,8 @@ fn cargo_default_env_metadata_env_var() {
-C extra-filename=[..] \
--out-dir [..] \
-L dependency=[CWD]/target/debug/deps \
--extern bar=[CWD]/target/debug/deps/{prefix}bar-[..]{suffix}`
--extern 'priv:bar=[CWD]/target/debug/deps/{prefix}bar-[..]{suffix}' \
-Z unstable-options`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
prefix = env::consts::DLL_PREFIX,
Expand Down Expand Up @@ -2445,8 +2447,9 @@ fn verbose_release_build_deps() {
-C metadata=[..] \
--out-dir [..] \
-L dependency=[CWD]/target/release/deps \
--extern foo=[CWD]/target/release/deps/{prefix}foo{suffix} \
--extern foo=[CWD]/target/release/deps/libfoo.rlib`
--extern 'priv:foo=[CWD]/target/release/deps/{prefix}foo{suffix}' \
--extern 'priv:foo=[CWD]/target/release/deps/libfoo.rlib' \
-Z unstable-options`
[FINISHED] release [optimized] target(s) in [..]
",
prefix = env::consts::DLL_PREFIX,
Expand Down
2 changes: 1 addition & 1 deletion tests/testsuite/build_script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3018,7 +3018,7 @@ fn diamond_passes_args_only_once() {
[COMPILING] a v0.5.0 ([..]
[RUNNING] `rustc [..]`
[COMPILING] foo v0.5.0 ([..]
[RUNNING] `[..]rmeta -L native=test`
[RUNNING] `[..] --extern 'priv:a=[..]rmeta' --extern 'priv:b=[..]rmeta' -Z unstable-options -L native=test`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
Expand Down
1 change: 1 addition & 0 deletions tests/testsuite/cargo/z_help/stdout.log
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Available unstable (nightly-only) flags:
-Z panic-abort-tests Enable support to run tests with -Cpanic=abort
-Z precise-pre-release Enable pre-release versions to be selected with `update --precise`
-Z profile-rustflags Enable the `rustflags` option in profiles in .cargo/config.toml file
-Z public-dependency Enable public-dependency to allow marking dependencies as public/private
-Z publish-timeout Enable the `publish.timeout` key in .cargo/config.toml file
-Z rustdoc-map Allow passing external documentation mappings to rustdoc
-Z rustdoc-scrape-examples Allows Rustdoc to scrape code examples from reverse-dependencies
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
cargo-features = ["public-dependency"]
[package]
name = "bar"
version = "0.0.0"
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
cargo-features = ["public-dependency"]
[package]
name = "bar"
version = "0.0.0"
Expand Down
1 change: 0 additions & 1 deletion tests/testsuite/cargo_add/no_public/in/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
cargo-features = ["public-dependency"]
[workspace]

[package]
Expand Down
Loading

0 comments on commit 2fff2fd

Please sign in to comment.