feat(resolver): Respect MSRV

This commit is contained in:
Ed Page 2023-08-25 10:42:26 -05:00
parent 10196aaee3
commit 4820624ce7
16 changed files with 74 additions and 7 deletions

View File

@ -31,6 +31,7 @@ fn do_resolve<'cfg>(config: &'cfg Config, ws_root: &Path) -> ResolveInfo<'cfg> {
let specs = pkgs.to_package_id_specs(&ws).unwrap();
let has_dev_units = HasDevUnits::Yes;
let force_all_targets = ForceAllTargets::No;
let max_rust_version = None;
// Do an initial run to download anything necessary so that it does
// not confuse criterion's warmup.
let ws_resolve = cargo::ops::resolve_ws_with_opts(
@ -41,6 +42,7 @@ fn do_resolve<'cfg>(config: &'cfg Config, ws_root: &Path) -> ResolveInfo<'cfg> {
&specs,
has_dev_units,
force_all_targets,
max_rust_version,
)
.unwrap();
ResolveInfo {
@ -82,6 +84,7 @@ fn resolve_ws(c: &mut Criterion) {
force_all_targets,
..
} = lazy_info.get_or_insert_with(|| do_resolve(&config, &ws_root));
let max_rust_version = None;
b.iter(|| {
cargo::ops::resolve_ws_with_opts(
ws,
@ -91,6 +94,7 @@ fn resolve_ws(c: &mut Criterion) {
specs,
*has_dev_units,
*force_all_targets,
max_rust_version,
)
.unwrap();
})

View File

@ -188,6 +188,7 @@ pub fn resolve_with_config_raw(
.unwrap();
let opts = ResolveOpts::everything();
let start = Instant::now();
let max_rust_version = None;
let resolve = resolver::resolve(
&[(summary, opts)],
&[],
@ -195,6 +196,7 @@ pub fn resolve_with_config_raw(
&VersionPreferences::default(),
Some(config),
true,
max_rust_version,
);
// The largest test in our suite takes less then 30 sec.

View File

@ -145,6 +145,7 @@ pub fn resolve_std<'cfg>(
let cli_features = CliFeatures::from_command_line(
&features, /*all_features*/ false, /*uses_default_features*/ false,
)?;
let max_rust_version = ws.rust_version();
let resolve = ops::resolve_ws_with_opts(
&std_ws,
target_data,
@ -153,6 +154,7 @@ pub fn resolve_std<'cfg>(
&specs,
HasDevUnits::No,
crate::core::resolver::features::ForceAllTargets::No,
max_rust_version,
)?;
Ok((
resolve.pkg_set,

View File

@ -21,6 +21,7 @@ use crate::core::{
};
use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
use crate::util::PartialVersion;
use anyhow::Context as _;
use std::collections::{BTreeSet, HashMap, HashSet};
@ -36,6 +37,7 @@ pub struct RegistryQueryer<'a> {
/// versions first. That allows `cargo update -Z minimal-versions` which will
/// specify minimum dependency versions to be used.
minimal_versions: bool,
max_rust_version: Option<PartialVersion>,
/// a cache of `Candidate`s that fulfil a `Dependency` (and whether `first_minimal_version`)
registry_cache: HashMap<(Dependency, bool), Poll<Rc<Vec<Summary>>>>,
/// a cache of `Dependency`s that are required for a `Summary`
@ -57,12 +59,14 @@ impl<'a> RegistryQueryer<'a> {
replacements: &'a [(PackageIdSpec, Dependency)],
version_prefs: &'a VersionPreferences,
minimal_versions: bool,
max_rust_version: Option<PartialVersion>,
) -> Self {
RegistryQueryer {
registry,
replacements,
version_prefs,
minimal_versions,
max_rust_version,
registry_cache: HashMap::new(),
summary_cache: HashMap::new(),
used_replacements: HashMap::new(),
@ -112,7 +116,9 @@ impl<'a> RegistryQueryer<'a> {
let mut ret = Vec::new();
let ready = self.registry.query(dep, QueryKind::Exact, &mut |s| {
ret.push(s);
if self.max_rust_version.is_none() || s.rust_version() <= self.max_rust_version {
ret.push(s);
}
})?;
if ready.is_pending() {
self.registry_cache

View File

@ -71,6 +71,7 @@ use crate::util::config::Config;
use crate::util::errors::CargoResult;
use crate::util::network::PollExt;
use crate::util::profile;
use crate::util::PartialVersion;
use self::context::Context;
use self::dep_cache::RegistryQueryer;
@ -138,6 +139,7 @@ pub fn resolve(
version_prefs: &VersionPreferences,
config: Option<&Config>,
check_public_visible_dependencies: bool,
mut max_rust_version: Option<PartialVersion>,
) -> CargoResult<Resolve> {
let _p = profile::start("resolving");
let minimal_versions = match config {
@ -148,8 +150,19 @@ pub fn resolve(
Some(config) => config.cli_unstable().direct_minimal_versions,
None => false,
};
let mut registry =
RegistryQueryer::new(registry, replacements, version_prefs, minimal_versions);
if !config
.map(|c| c.cli_unstable().msrv_policy)
.unwrap_or(false)
{
max_rust_version = None;
}
let mut registry = RegistryQueryer::new(
registry,
replacements,
version_prefs,
minimal_versions,
max_rust_version,
);
let cx = loop {
let cx = Context::new(check_public_visible_dependencies);
let cx = activate_deps_loop(

View File

@ -23,6 +23,7 @@ use crate::util::edit_distance;
use crate::util::errors::{CargoResult, ManifestError};
use crate::util::interning::InternedString;
use crate::util::toml::{read_manifest, InheritableFields, TomlDependency, TomlProfiles};
use crate::util::PartialVersion;
use crate::util::{config::ConfigRelativePath, Config, Filesystem, IntoUrl};
use cargo_util::paths;
use cargo_util::paths::normalize_path;
@ -595,6 +596,12 @@ impl<'cfg> Workspace<'cfg> {
self
}
/// Get the lowest-common denominator `package.rust-version` within the workspace, if specified
/// anywhere
pub fn rust_version(&self) -> Option<PartialVersion> {
self.members().filter_map(|pkg| pkg.rust_version()).min()
}
pub fn custom_metadata(&self) -> Option<&toml::Value> {
self.custom_metadata.as_ref()
}

View File

@ -261,6 +261,7 @@ pub fn create_bcx<'a, 'cfg>(
HasDevUnits::No
}
};
let max_rust_version = ws.rust_version();
let resolve = ops::resolve_ws_with_opts(
ws,
&mut target_data,
@ -269,6 +270,7 @@ pub fn create_bcx<'a, 'cfg>(
&specs,
has_dev_units,
crate::core::resolver::features::ForceAllTargets::No,
max_rust_version,
)?;
let WorkspaceResolve {
mut pkg_set,

View File

@ -21,6 +21,7 @@ pub struct UpdateOptions<'a> {
pub fn generate_lockfile(ws: &Workspace<'_>) -> CargoResult<()> {
let mut registry = PackageRegistry::new(ws.config())?;
let max_rust_version = ws.rust_version();
let mut resolve = ops::resolve_with_previous(
&mut registry,
ws,
@ -30,6 +31,7 @@ pub fn generate_lockfile(ws: &Workspace<'_>) -> CargoResult<()> {
None,
&[],
true,
max_rust_version,
)?;
ops::write_pkg_lockfile(ws, &mut resolve)?;
Ok(())
@ -48,6 +50,8 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
// that we're synchronized against other Cargos.
let _lock = ws.config().acquire_package_cache_lock()?;
let max_rust_version = ws.rust_version();
let previous_resolve = match ops::load_pkg_lockfile(ws)? {
Some(resolve) => resolve,
None => {
@ -67,6 +71,7 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
None,
&[],
true,
max_rust_version,
)?
}
}
@ -125,6 +130,7 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
Some(&to_avoid),
&[],
true,
max_rust_version,
)?;
// Summarize what is changing for the user.

View File

@ -135,6 +135,8 @@ fn build_resolve_graph(
crate::core::resolver::features::ForceAllTargets::No
};
let max_rust_version = ws.rust_version();
// Note that even with --filter-platform we end up downloading host dependencies as well,
// as that is the behavior of download_accessible.
let ws_resolve = ops::resolve_ws_with_opts(
@ -145,6 +147,7 @@ fn build_resolve_graph(
&specs,
HasDevUnits::Yes,
force_all,
max_rust_version,
)?;
let package_map: BTreeMap<PackageId, Package> = ws_resolve

View File

@ -423,6 +423,8 @@ fn build_lock(ws: &Workspace<'_>, orig_pkg: &Package) -> CargoResult<String> {
TomlManifest::to_real_manifest(&toml_manifest, false, source_id, package_root, config)?;
let new_pkg = Package::new(manifest, orig_pkg.manifest_path());
let max_rust_version = new_pkg.rust_version();
// Regenerate Cargo.lock using the old one as a guide.
let tmp_ws = Workspace::ephemeral(new_pkg, ws.config(), None, true)?;
let mut tmp_reg = PackageRegistry::new(ws.config())?;
@ -435,6 +437,7 @@ fn build_lock(ws: &Workspace<'_>, orig_pkg: &Package) -> CargoResult<String> {
None,
&[],
true,
max_rust_version,
)?;
let pkg_set = ops::get_resolved_packages(&new_resolve, tmp_reg)?;

View File

@ -246,6 +246,8 @@ fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<(
let mut target_data =
RustcTargetData::new(ws, &opts.compile_opts.build_config.requested_kinds)?;
let mut resolve_differences = |has_dev_units| -> CargoResult<(WorkspaceResolve<'_>, DiffMap)> {
let max_rust_version = ws.rust_version();
let ws_resolve = ops::resolve_ws_with_opts(
ws,
&mut target_data,
@ -254,6 +256,7 @@ fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<(
&specs,
has_dev_units,
crate::core::resolver::features::ForceAllTargets::No,
max_rust_version,
)?;
let feature_opts = FeatureOpts::new_behavior(ResolveBehavior::V2, has_dev_units);

View File

@ -69,6 +69,7 @@ use crate::core::{GitReference, PackageId, PackageIdSpec, PackageSet, SourceId,
use crate::ops;
use crate::sources::PathSource;
use crate::util::errors::CargoResult;
use crate::util::PartialVersion;
use crate::util::{profile, CanonicalUrl};
use anyhow::Context as _;
use std::collections::{HashMap, HashSet};
@ -106,8 +107,10 @@ version. This may also occur with an optional dependency that is not enabled.";
/// This is a simple interface used by commands like `clean`, `fetch`, and
/// `package`, which don't specify any options or features.
pub fn resolve_ws<'a>(ws: &Workspace<'a>) -> CargoResult<(PackageSet<'a>, Resolve)> {
let max_rust_version = ws.rust_version();
let mut registry = PackageRegistry::new(ws.config())?;
let resolve = resolve_with_registry(ws, &mut registry)?;
let resolve = resolve_with_registry(ws, &mut registry, max_rust_version)?;
let packages = get_resolved_packages(&resolve, registry)?;
Ok((packages, resolve))
}
@ -130,6 +133,7 @@ pub fn resolve_ws_with_opts<'cfg>(
specs: &[PackageIdSpec],
has_dev_units: HasDevUnits,
force_all_targets: ForceAllTargets,
max_rust_version: Option<PartialVersion>,
) -> CargoResult<WorkspaceResolve<'cfg>> {
let mut registry = PackageRegistry::new(ws.config())?;
let mut add_patches = true;
@ -138,7 +142,7 @@ pub fn resolve_ws_with_opts<'cfg>(
} else if ws.require_optional_deps() {
// First, resolve the root_package's *listed* dependencies, as well as
// downloading and updating all remotes and such.
let resolve = resolve_with_registry(ws, &mut registry)?;
let resolve = resolve_with_registry(ws, &mut registry, max_rust_version)?;
// No need to add patches again, `resolve_with_registry` has done it.
add_patches = false;
@ -184,6 +188,7 @@ pub fn resolve_ws_with_opts<'cfg>(
None,
specs,
add_patches,
max_rust_version,
)?;
let pkg_set = get_resolved_packages(&resolved_with_overrides, registry)?;
@ -235,6 +240,7 @@ pub fn resolve_ws_with_opts<'cfg>(
fn resolve_with_registry<'cfg>(
ws: &Workspace<'cfg>,
registry: &mut PackageRegistry<'cfg>,
max_rust_version: Option<PartialVersion>,
) -> CargoResult<Resolve> {
let prev = ops::load_pkg_lockfile(ws)?;
let mut resolve = resolve_with_previous(
@ -246,6 +252,7 @@ fn resolve_with_registry<'cfg>(
None,
&[],
true,
max_rust_version,
)?;
if !ws.is_ephemeral() && ws.require_optional_deps() {
@ -278,6 +285,7 @@ pub fn resolve_with_previous<'cfg>(
to_avoid: Option<&HashSet<PackageId>>,
specs: &[PackageIdSpec],
register_patches: bool,
max_rust_version: Option<PartialVersion>,
) -> CargoResult<Resolve> {
// We only want one Cargo at a time resolving a crate graph since this can
// involve a lot of frobbing of the global caches.
@ -505,6 +513,7 @@ pub fn resolve_with_previous<'cfg>(
ws.unstable_features()
.require(Feature::public_dependency())
.is_ok(),
max_rust_version,
)?;
let patches: Vec<_> = registry
.patches()

View File

@ -150,6 +150,7 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
} else {
ForceAllTargets::No
};
let max_rust_version = ws.rust_version();
let ws_resolve = ops::resolve_ws_with_opts(
ws,
&mut target_data,
@ -158,6 +159,7 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
&specs,
has_dev,
force_all,
max_rust_version,
)?;
let package_map: HashMap<PackageId, &Package> = ws_resolve

View File

@ -108,7 +108,7 @@ impl From<VersionReq> for OptVersionReq {
}
}
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone, Debug)]
pub struct PartialVersion {
pub major: u64,
pub minor: Option<u64>,

View File

@ -26,7 +26,7 @@ fn case() {
.current_dir(cwd)
.masquerade_as_nightly_cargo(&["msrv-policy"])
.assert()
.success()
.code(101)
.stdout_matches_path(curr_dir!().join("stdout.log"))
.stderr_matches_path(curr_dir!().join("stderr.log"));

View File

@ -1,2 +1,7 @@
Updating `dummy-registry` index
Adding rust-version-user v0.2.1 to dependencies.
error: failed to select a version for the requirement `rust-version-user = "^0.2.1"`
candidate versions found which didn't match: 0.2.1, 0.1.0
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
required by package `cargo-list-test-fixture v0.0.0 ([ROOT]/case)`
perhaps a crate was updated and forgotten to be re-vendored?