Skip to content

Commit

Permalink
Auto merge of rust-lang#8129 - ehuss:resolver-behavior, r=alexcrichton
Browse files Browse the repository at this point in the history
Add `resolver` opt-in for new feature resolver.

This adds a new `resolver` field to `Cargo.toml` to provide an opt-in mechanism for backwards-incompatible resolver changes. This enables the new feature resolver and `-Zpackage-features`. See `unstable.md` for documentation.

cc rust-lang#8088
  • Loading branch information
bors committed Apr 20, 2020
2 parents 3c8c94b + 323d7a8 commit c374809
Show file tree
Hide file tree
Showing 15 changed files with 662 additions and 76 deletions.
37 changes: 22 additions & 15 deletions crates/cargo-test-support/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,27 @@ impl Package {
}

fn make_archive(&self) {
let dst = self.archive_dst();
t!(fs::create_dir_all(dst.parent().unwrap()));
let f = t!(File::create(&dst));
let mut a = Builder::new(GzEncoder::new(f, Compression::default()));

if !self.files.iter().any(|(name, _)| name == "Cargo.toml") {
self.append_manifest(&mut a);
}
if self.files.is_empty() {
self.append(&mut a, "src/lib.rs", "");
} else {
for &(ref name, ref contents) in self.files.iter() {
self.append(&mut a, name, contents);
}
}
for &(ref name, ref contents) in self.extra_files.iter() {
self.append_extra(&mut a, name, contents);
}
}

fn append_manifest<W: Write>(&self, ar: &mut Builder<W>) {
let mut manifest = format!(
r#"
[package]
Expand Down Expand Up @@ -508,21 +529,7 @@ impl Package {
manifest.push_str("[lib]\nproc-macro = true\n");
}

let dst = self.archive_dst();
t!(fs::create_dir_all(dst.parent().unwrap()));
let f = t!(File::create(&dst));
let mut a = Builder::new(GzEncoder::new(f, Compression::default()));
self.append(&mut a, "Cargo.toml", &manifest);
if self.files.is_empty() {
self.append(&mut a, "src/lib.rs", "");
} else {
for &(ref name, ref contents) in self.files.iter() {
self.append(&mut a, name, contents);
}
}
for &(ref name, ref contents) in self.extra_files.iter() {
self.append_extra(&mut a, name, contents);
}
self.append(ar, "Cargo.toml", &manifest);
}

fn append<W: Write>(&self, ar: &mut Builder<W>, file: &str, contents: &str) {
Expand Down
1 change: 1 addition & 0 deletions src/cargo/core/compiler/standard_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub fn resolve_std<'cfg>(
ws_config,
/*profiles*/ None,
crate::core::Features::default(),
None,
);

let config = ws.config();
Expand Down
3 changes: 3 additions & 0 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ features! {

// Allow to specify profiles other than 'dev', 'release', 'test', etc.
[unstable] named_profiles: bool,

// Opt-in new-resolver behavior.
[unstable] resolver: bool,
}
}

Expand Down
21 changes: 21 additions & 0 deletions src/cargo/core/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use serde::Serialize;
use url::Url;

use crate::core::interning::InternedString;
use crate::core::resolver::ResolveBehavior;
use crate::core::{Dependency, PackageId, PackageIdSpec, SourceId, Summary};
use crate::core::{Edition, Feature, Features, WorkspaceConfig};
use crate::util::errors::*;
Expand Down Expand Up @@ -45,6 +46,7 @@ pub struct Manifest {
im_a_teapot: Option<bool>,
default_run: Option<String>,
metabuild: Option<Vec<String>>,
resolve_behavior: Option<ResolveBehavior>,
}

/// When parsing `Cargo.toml`, some warnings should silenced
Expand All @@ -67,6 +69,7 @@ pub struct VirtualManifest {
profiles: Option<TomlProfiles>,
warnings: Warnings,
features: Features,
resolve_behavior: Option<ResolveBehavior>,
}

/// General metadata about a package which is just blindly uploaded to the
Expand Down Expand Up @@ -421,6 +424,7 @@ impl Manifest {
default_run: Option<String>,
original: Rc<TomlManifest>,
metabuild: Option<Vec<String>>,
resolve_behavior: Option<ResolveBehavior>,
) -> Manifest {
Manifest {
summary,
Expand All @@ -443,6 +447,7 @@ impl Manifest {
default_run,
publish_lockfile,
metabuild,
resolve_behavior,
}
}

Expand Down Expand Up @@ -509,6 +514,13 @@ impl Manifest {
&self.features
}

/// The style of resolver behavior to use, declared with the `resolver` field.
///
/// Returns `None` if it is not specified.
pub fn resolve_behavior(&self) -> Option<ResolveBehavior> {
self.resolve_behavior
}

pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Manifest {
Manifest {
summary: self.summary.map_source(to_replace, replace_with),
Expand Down Expand Up @@ -572,6 +584,7 @@ impl VirtualManifest {
workspace: WorkspaceConfig,
profiles: Option<TomlProfiles>,
features: Features,
resolve_behavior: Option<ResolveBehavior>,
) -> VirtualManifest {
VirtualManifest {
replace,
Expand All @@ -580,6 +593,7 @@ impl VirtualManifest {
profiles,
warnings: Warnings::new(),
features,
resolve_behavior,
}
}

Expand Down Expand Up @@ -610,6 +624,13 @@ impl VirtualManifest {
pub fn features(&self) -> &Features {
&self.features
}

/// The style of resolver behavior to use, declared with the `resolver` field.
///
/// Returns `None` if it is not specified.
pub fn resolve_behavior(&self) -> Option<ResolveBehavior> {
self.resolve_behavior
}
}

impl Target {
Expand Down
38 changes: 18 additions & 20 deletions src/cargo/core/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,27 @@ use crate::core::interning::InternedString;
use crate::core::resolver::{HasDevUnits, Resolve};
use crate::core::source::MaybePackage;
use crate::core::{Dependency, Manifest, PackageId, SourceId, Target};
use crate::core::{FeatureMap, SourceMap, Summary};
use crate::core::{FeatureMap, SourceMap, Summary, Workspace};
use crate::ops;
use crate::util::config::PackageCacheLock;
use crate::util::errors::{CargoResult, CargoResultExt, HttpNot200};
use crate::util::network::Retry;
use crate::util::{self, internal, Config, Progress, ProgressStyle};

pub const MANIFEST_PREAMBLE: &str = "\
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# \"normalize\" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
";

/// Information about a package that is available somewhere in the file system.
///
/// A package is a `Cargo.toml` file plus all the files that are part of it.
Expand Down Expand Up @@ -219,29 +233,13 @@ impl Package {
}
}

pub fn to_registry_toml(&self, config: &Config) -> CargoResult<String> {
pub fn to_registry_toml(&self, ws: &Workspace<'_>) -> CargoResult<String> {
let manifest = self
.manifest()
.original()
.prepare_for_publish(config, self.root())?;
.prepare_for_publish(ws, self.root())?;
let toml = toml::to_string(&manifest)?;
Ok(format!(
"# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n\
#\n\
# When uploading crates to the registry Cargo will automatically\n\
# \"normalize\" Cargo.toml files for maximal compatibility\n\
# with all versions of Cargo and also rewrite `path` dependencies\n\
# to registry (e.g., crates.io) dependencies\n\
#\n\
# If you believe there's an error in this file please file an\n\
# issue against the rust-lang/cargo repository. If you're\n\
# editing this file be aware that the upstream Cargo.toml\n\
# will likely look very different (and much more reasonable)\n\
\n\
{}\
",
toml
))
Ok(format!("{}\n{}", MANIFEST_PREAMBLE, toml))
}

/// Returns if package should include `Cargo.lock`.
Expand Down
17 changes: 12 additions & 5 deletions src/cargo/core/resolver/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@
use crate::core::compiler::{CompileKind, RustcTargetData};
use crate::core::dependency::{DepKind, Dependency};
use crate::core::resolver::types::FeaturesSet;
use crate::core::resolver::Resolve;
use crate::core::resolver::{Resolve, ResolveBehavior};
use crate::core::{FeatureValue, InternedString, PackageId, PackageIdSpec, PackageSet, Workspace};
use crate::util::{CargoResult, Config};
use crate::util::CargoResult;
use std::collections::{BTreeSet, HashMap, HashSet};
use std::rc::Rc;

Expand Down Expand Up @@ -110,9 +110,9 @@ impl FeaturesFor {
}

impl FeatureOpts {
fn new(config: &Config, has_dev_units: HasDevUnits) -> CargoResult<FeatureOpts> {
fn new(ws: &Workspace<'_>, has_dev_units: HasDevUnits) -> CargoResult<FeatureOpts> {
let mut opts = FeatureOpts::default();
let unstable_flags = config.cli_unstable();
let unstable_flags = ws.config().cli_unstable();
opts.package_features = unstable_flags.package_features;
let mut enable = |feat_opts: &Vec<String>| {
opts.new_resolver = true;
Expand All @@ -136,6 +136,12 @@ impl FeatureOpts {
if let Some(feat_opts) = unstable_flags.features.as_ref() {
enable(feat_opts)?;
}
match ws.resolve_behavior() {
ResolveBehavior::V1 => {}
ResolveBehavior::V2 => {
enable(&vec!["all".to_string()]).unwrap();
}
}
// This env var is intended for testing only.
if let Ok(env_opts) = std::env::var("__CARGO_FORCE_NEW_FEATURES") {
if env_opts == "1" {
Expand All @@ -146,6 +152,7 @@ impl FeatureOpts {
}
}
if let HasDevUnits::Yes = has_dev_units {
// Dev deps cannot be decoupled when they are in use.
opts.decouple_dev_deps = false;
}
Ok(opts)
Expand Down Expand Up @@ -268,7 +275,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
use crate::util::profile;
let _p = profile::start("resolve features");

let opts = FeatureOpts::new(ws.config(), has_dev_units)?;
let opts = FeatureOpts::new(ws, has_dev_units)?;
if !opts.new_resolver {
// Legacy mode.
return Ok(ResolvedFeatures {
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/core/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub use self::encode::{EncodableDependency, EncodablePackageId, EncodableResolve
pub use self::errors::{ActivateError, ActivateResult, ResolveError};
pub use self::features::HasDevUnits;
pub use self::resolve::{Resolve, ResolveVersion};
pub use self::types::ResolveOpts;
pub use self::types::{ResolveBehavior, ResolveOpts};

mod conflict_cache;
mod context;
Expand Down
29 changes: 29 additions & 0 deletions src/cargo/core/resolver/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,35 @@ impl ResolverProgress {
/// optimized comparison operators like `is_subset` at the interfaces.
pub type FeaturesSet = Rc<BTreeSet<InternedString>>;

/// Resolver behavior, used to opt-in to new behavior that is
/// backwards-incompatible via the `resolver` field in the manifest.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum ResolveBehavior {
/// V1 is the original resolver behavior.
V1,
/// V2 adds the new feature resolver.
V2,
}

impl ResolveBehavior {
pub fn from_manifest(resolver: &str) -> CargoResult<ResolveBehavior> {
match resolver {
"2" => Ok(ResolveBehavior::V2),
s => anyhow::bail!(
"`resolver` setting `{}` is not valid, only valid option is \"2\"",
s
),
}
}

pub fn to_manifest(&self) -> Option<String> {
match self {
ResolveBehavior::V1 => None,
ResolveBehavior::V2 => Some("2".to_string()),
}
}
}

/// Options for how the resolve should work.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct ResolveOpts {
Expand Down
Loading

0 comments on commit c374809

Please sign in to comment.