From 08ed8de4d1864336b406004f2acd20d3f2b9b613 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 25 Apr 2025 09:21:09 -0500 Subject: [PATCH] fix(resolver): Suggest similar looking features --- src/cargo/core/resolver/errors.rs | 10 +++++++++- tests/testsuite/features.rs | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cargo/core/resolver/errors.rs b/src/cargo/core/resolver/errors.rs index d743e2622..169fcd1fa 100644 --- a/src/cargo/core/resolver/errors.rs +++ b/src/cargo/core/resolver/errors.rs @@ -5,7 +5,7 @@ use std::task::Poll; use crate::core::{Dependency, PackageId, Registry, Summary}; use crate::sources::source::QueryKind; use crate::sources::IndexSummary; -use crate::util::edit_distance::edit_distance; +use crate::util::edit_distance::{closest, edit_distance}; use crate::util::errors::CargoResult; use crate::util::{GlobalContext, OptVersionReq, VersionExt}; use anyhow::Error; @@ -160,6 +160,14 @@ pub(super) fn activation_error( msg.push_str("` but `"); msg.push_str(&*dep.package_name()); msg.push_str("` does not have that feature.\n"); + let latest = candidates.last().expect("in the non-empty branch"); + if let Some(closest) = closest(feature, latest.features().keys(), |k| k) { + msg.push_str(" package `"); + msg.push_str(&*dep.package_name()); + msg.push_str("` does have feature `"); + msg.push_str(closest); + msg.push_str("`\n"); + } // p == parent so the full path is redundant. } ConflictReason::RequiredDependencyAsFeature(feature) => { diff --git a/tests/testsuite/features.rs b/tests/testsuite/features.rs index 336205759..da39e16bc 100644 --- a/tests/testsuite/features.rs +++ b/tests/testsuite/features.rs @@ -280,6 +280,7 @@ fn dependency_activates_typoed_feature() { versions that meet the requirements `*` are: 0.0.1 package `foo` depends on `bar` with feature `bar` but `bar` does not have that feature. + package `bar` does have feature `baz` failed to select a version for `bar` which could resolve this conflict