Skip to content

Commit c374809

Browse files
committed
Auto merge of #8129 - ehuss:resolver-behavior, r=alexcrichton
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 #8088
2 parents 3c8c94b + 323d7a8 commit c374809

File tree

15 files changed

+662
-76
lines changed

15 files changed

+662
-76
lines changed

crates/cargo-test-support/src/registry.rs

+22-15
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,27 @@ impl Package {
473473
}
474474

475475
fn make_archive(&self) {
476+
let dst = self.archive_dst();
477+
t!(fs::create_dir_all(dst.parent().unwrap()));
478+
let f = t!(File::create(&dst));
479+
let mut a = Builder::new(GzEncoder::new(f, Compression::default()));
480+
481+
if !self.files.iter().any(|(name, _)| name == "Cargo.toml") {
482+
self.append_manifest(&mut a);
483+
}
484+
if self.files.is_empty() {
485+
self.append(&mut a, "src/lib.rs", "");
486+
} else {
487+
for &(ref name, ref contents) in self.files.iter() {
488+
self.append(&mut a, name, contents);
489+
}
490+
}
491+
for &(ref name, ref contents) in self.extra_files.iter() {
492+
self.append_extra(&mut a, name, contents);
493+
}
494+
}
495+
496+
fn append_manifest<W: Write>(&self, ar: &mut Builder<W>) {
476497
let mut manifest = format!(
477498
r#"
478499
[package]
@@ -508,21 +529,7 @@ impl Package {
508529
manifest.push_str("[lib]\nproc-macro = true\n");
509530
}
510531

511-
let dst = self.archive_dst();
512-
t!(fs::create_dir_all(dst.parent().unwrap()));
513-
let f = t!(File::create(&dst));
514-
let mut a = Builder::new(GzEncoder::new(f, Compression::default()));
515-
self.append(&mut a, "Cargo.toml", &manifest);
516-
if self.files.is_empty() {
517-
self.append(&mut a, "src/lib.rs", "");
518-
} else {
519-
for &(ref name, ref contents) in self.files.iter() {
520-
self.append(&mut a, name, contents);
521-
}
522-
}
523-
for &(ref name, ref contents) in self.extra_files.iter() {
524-
self.append_extra(&mut a, name, contents);
525-
}
532+
self.append(ar, "Cargo.toml", &manifest);
526533
}
527534

528535
fn append<W: Write>(&self, ar: &mut Builder<W>, file: &str, contents: &str) {

src/cargo/core/compiler/standard_lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ pub fn resolve_std<'cfg>(
7272
ws_config,
7373
/*profiles*/ None,
7474
crate::core::Features::default(),
75+
None,
7576
);
7677

7778
let config = ws.config();

src/cargo/core/features.rs

+3
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@ features! {
211211

212212
// Allow to specify profiles other than 'dev', 'release', 'test', etc.
213213
[unstable] named_profiles: bool,
214+
215+
// Opt-in new-resolver behavior.
216+
[unstable] resolver: bool,
214217
}
215218
}
216219

src/cargo/core/manifest.rs

+21
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use serde::Serialize;
1111
use url::Url;
1212

1313
use crate::core::interning::InternedString;
14+
use crate::core::resolver::ResolveBehavior;
1415
use crate::core::{Dependency, PackageId, PackageIdSpec, SourceId, Summary};
1516
use crate::core::{Edition, Feature, Features, WorkspaceConfig};
1617
use crate::util::errors::*;
@@ -45,6 +46,7 @@ pub struct Manifest {
4546
im_a_teapot: Option<bool>,
4647
default_run: Option<String>,
4748
metabuild: Option<Vec<String>>,
49+
resolve_behavior: Option<ResolveBehavior>,
4850
}
4951

5052
/// When parsing `Cargo.toml`, some warnings should silenced
@@ -67,6 +69,7 @@ pub struct VirtualManifest {
6769
profiles: Option<TomlProfiles>,
6870
warnings: Warnings,
6971
features: Features,
72+
resolve_behavior: Option<ResolveBehavior>,
7073
}
7174

7275
/// General metadata about a package which is just blindly uploaded to the
@@ -421,6 +424,7 @@ impl Manifest {
421424
default_run: Option<String>,
422425
original: Rc<TomlManifest>,
423426
metabuild: Option<Vec<String>>,
427+
resolve_behavior: Option<ResolveBehavior>,
424428
) -> Manifest {
425429
Manifest {
426430
summary,
@@ -443,6 +447,7 @@ impl Manifest {
443447
default_run,
444448
publish_lockfile,
445449
metabuild,
450+
resolve_behavior,
446451
}
447452
}
448453

@@ -509,6 +514,13 @@ impl Manifest {
509514
&self.features
510515
}
511516

517+
/// The style of resolver behavior to use, declared with the `resolver` field.
518+
///
519+
/// Returns `None` if it is not specified.
520+
pub fn resolve_behavior(&self) -> Option<ResolveBehavior> {
521+
self.resolve_behavior
522+
}
523+
512524
pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Manifest {
513525
Manifest {
514526
summary: self.summary.map_source(to_replace, replace_with),
@@ -572,6 +584,7 @@ impl VirtualManifest {
572584
workspace: WorkspaceConfig,
573585
profiles: Option<TomlProfiles>,
574586
features: Features,
587+
resolve_behavior: Option<ResolveBehavior>,
575588
) -> VirtualManifest {
576589
VirtualManifest {
577590
replace,
@@ -580,6 +593,7 @@ impl VirtualManifest {
580593
profiles,
581594
warnings: Warnings::new(),
582595
features,
596+
resolve_behavior,
583597
}
584598
}
585599

@@ -610,6 +624,13 @@ impl VirtualManifest {
610624
pub fn features(&self) -> &Features {
611625
&self.features
612626
}
627+
628+
/// The style of resolver behavior to use, declared with the `resolver` field.
629+
///
630+
/// Returns `None` if it is not specified.
631+
pub fn resolve_behavior(&self) -> Option<ResolveBehavior> {
632+
self.resolve_behavior
633+
}
613634
}
614635

615636
impl Target {

src/cargo/core/package.rs

+18-20
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,27 @@ use crate::core::interning::InternedString;
2424
use crate::core::resolver::{HasDevUnits, Resolve};
2525
use crate::core::source::MaybePackage;
2626
use crate::core::{Dependency, Manifest, PackageId, SourceId, Target};
27-
use crate::core::{FeatureMap, SourceMap, Summary};
27+
use crate::core::{FeatureMap, SourceMap, Summary, Workspace};
2828
use crate::ops;
2929
use crate::util::config::PackageCacheLock;
3030
use crate::util::errors::{CargoResult, CargoResultExt, HttpNot200};
3131
use crate::util::network::Retry;
3232
use crate::util::{self, internal, Config, Progress, ProgressStyle};
3333

34+
pub const MANIFEST_PREAMBLE: &str = "\
35+
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
36+
#
37+
# When uploading crates to the registry Cargo will automatically
38+
# \"normalize\" Cargo.toml files for maximal compatibility
39+
# with all versions of Cargo and also rewrite `path` dependencies
40+
# to registry (e.g., crates.io) dependencies
41+
#
42+
# If you believe there's an error in this file please file an
43+
# issue against the rust-lang/cargo repository. If you're
44+
# editing this file be aware that the upstream Cargo.toml
45+
# will likely look very different (and much more reasonable)
46+
";
47+
3448
/// Information about a package that is available somewhere in the file system.
3549
///
3650
/// A package is a `Cargo.toml` file plus all the files that are part of it.
@@ -219,29 +233,13 @@ impl Package {
219233
}
220234
}
221235

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

247245
/// Returns if package should include `Cargo.lock`.

src/cargo/core/resolver/features.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@
4141
use crate::core::compiler::{CompileKind, RustcTargetData};
4242
use crate::core::dependency::{DepKind, Dependency};
4343
use crate::core::resolver::types::FeaturesSet;
44-
use crate::core::resolver::Resolve;
44+
use crate::core::resolver::{Resolve, ResolveBehavior};
4545
use crate::core::{FeatureValue, InternedString, PackageId, PackageIdSpec, PackageSet, Workspace};
46-
use crate::util::{CargoResult, Config};
46+
use crate::util::CargoResult;
4747
use std::collections::{BTreeSet, HashMap, HashSet};
4848
use std::rc::Rc;
4949

@@ -110,9 +110,9 @@ impl FeaturesFor {
110110
}
111111

112112
impl FeatureOpts {
113-
fn new(config: &Config, has_dev_units: HasDevUnits) -> CargoResult<FeatureOpts> {
113+
fn new(ws: &Workspace<'_>, has_dev_units: HasDevUnits) -> CargoResult<FeatureOpts> {
114114
let mut opts = FeatureOpts::default();
115-
let unstable_flags = config.cli_unstable();
115+
let unstable_flags = ws.config().cli_unstable();
116116
opts.package_features = unstable_flags.package_features;
117117
let mut enable = |feat_opts: &Vec<String>| {
118118
opts.new_resolver = true;
@@ -136,6 +136,12 @@ impl FeatureOpts {
136136
if let Some(feat_opts) = unstable_flags.features.as_ref() {
137137
enable(feat_opts)?;
138138
}
139+
match ws.resolve_behavior() {
140+
ResolveBehavior::V1 => {}
141+
ResolveBehavior::V2 => {
142+
enable(&vec!["all".to_string()]).unwrap();
143+
}
144+
}
139145
// This env var is intended for testing only.
140146
if let Ok(env_opts) = std::env::var("__CARGO_FORCE_NEW_FEATURES") {
141147
if env_opts == "1" {
@@ -146,6 +152,7 @@ impl FeatureOpts {
146152
}
147153
}
148154
if let HasDevUnits::Yes = has_dev_units {
155+
// Dev deps cannot be decoupled when they are in use.
149156
opts.decouple_dev_deps = false;
150157
}
151158
Ok(opts)
@@ -268,7 +275,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
268275
use crate::util::profile;
269276
let _p = profile::start("resolve features");
270277

271-
let opts = FeatureOpts::new(ws.config(), has_dev_units)?;
278+
let opts = FeatureOpts::new(ws, has_dev_units)?;
272279
if !opts.new_resolver {
273280
// Legacy mode.
274281
return Ok(ResolvedFeatures {

src/cargo/core/resolver/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ pub use self::encode::{EncodableDependency, EncodablePackageId, EncodableResolve
7171
pub use self::errors::{ActivateError, ActivateResult, ResolveError};
7272
pub use self::features::HasDevUnits;
7373
pub use self::resolve::{Resolve, ResolveVersion};
74-
pub use self::types::ResolveOpts;
74+
pub use self::types::{ResolveBehavior, ResolveOpts};
7575

7676
mod conflict_cache;
7777
mod context;

src/cargo/core/resolver/types.rs

+29
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,35 @@ impl ResolverProgress {
9797
/// optimized comparison operators like `is_subset` at the interfaces.
9898
pub type FeaturesSet = Rc<BTreeSet<InternedString>>;
9999

100+
/// Resolver behavior, used to opt-in to new behavior that is
101+
/// backwards-incompatible via the `resolver` field in the manifest.
102+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
103+
pub enum ResolveBehavior {
104+
/// V1 is the original resolver behavior.
105+
V1,
106+
/// V2 adds the new feature resolver.
107+
V2,
108+
}
109+
110+
impl ResolveBehavior {
111+
pub fn from_manifest(resolver: &str) -> CargoResult<ResolveBehavior> {
112+
match resolver {
113+
"2" => Ok(ResolveBehavior::V2),
114+
s => anyhow::bail!(
115+
"`resolver` setting `{}` is not valid, only valid option is \"2\"",
116+
s
117+
),
118+
}
119+
}
120+
121+
pub fn to_manifest(&self) -> Option<String> {
122+
match self {
123+
ResolveBehavior::V1 => None,
124+
ResolveBehavior::V2 => Some("2".to_string()),
125+
}
126+
}
127+
}
128+
100129
/// Options for how the resolve should work.
101130
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
102131
pub struct ResolveOpts {

0 commit comments

Comments
 (0)