@@ -82,6 +82,7 @@ pub(super) fn activation_error(
8282 cx. parents
8383 . path_to_bottom ( & parent. package_id ( ) )
8484 . into_iter ( )
85+ . map ( |( node, _) | node)
8586 . cloned ( )
8687 . collect ( ) ,
8788 )
@@ -90,9 +91,7 @@ pub(super) fn activation_error(
9091 if !candidates. is_empty ( ) {
9192 let mut msg = format ! ( "failed to select a version for `{}`." , dep. package_name( ) ) ;
9293 msg. push_str ( "\n ... required by " ) ;
93- msg. push_str ( & describe_path (
94- & cx. parents . path_to_bottom ( & parent. package_id ( ) ) ,
95- ) ) ;
94+ msg. push_str ( & describe_path_in_context ( cx, & parent. package_id ( ) ) ) ;
9695
9796 msg. push_str ( "\n versions that meet the requirements `" ) ;
9897 msg. push_str ( & dep. version_req ( ) . to_string ( ) ) ;
@@ -128,7 +127,7 @@ pub(super) fn activation_error(
128127 msg. push_str ( "`, but it conflicts with a previous package which links to `" ) ;
129128 msg. push_str ( link) ;
130129 msg. push_str ( "` as well:\n " ) ;
131- msg. push_str ( & describe_path ( & cx . parents . path_to_bottom ( p ) ) ) ;
130+ msg. push_str ( & describe_path_in_context ( cx , p ) ) ;
132131 msg. push_str ( "\n Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. " ) ;
133132 msg. push_str ( "Try to adjust your dependencies so that only one package uses the links ='" ) ;
134133 msg. push_str ( & * dep. package_name ( ) ) ;
@@ -197,7 +196,7 @@ pub(super) fn activation_error(
197196 for ( p, r) in & conflicting_activations {
198197 if let ConflictReason :: Semver = r {
199198 msg. push_str ( "\n \n previously selected " ) ;
200- msg. push_str ( & describe_path ( & cx . parents . path_to_bottom ( p ) ) ) ;
199+ msg. push_str ( & describe_path_in_context ( cx , p ) ) ;
201200 }
202201 }
203202 }
@@ -250,9 +249,7 @@ pub(super) fn activation_error(
250249 registry. describe_source( dep. source_id( ) ) ,
251250 ) ;
252251 msg. push_str ( "required by " ) ;
253- msg. push_str ( & describe_path (
254- & cx. parents . path_to_bottom ( & parent. package_id ( ) ) ,
255- ) ) ;
252+ msg. push_str ( & describe_path_in_context ( cx, & parent. package_id ( ) ) ) ;
256253
257254 // If we have a path dependency with a locked version, then this may
258255 // indicate that we updated a sub-package and forgot to run `cargo
@@ -330,9 +327,7 @@ pub(super) fn activation_error(
330327 }
331328 msg. push_str ( & format ! ( "location searched: {}\n " , dep. source_id( ) ) ) ;
332329 msg. push_str ( "required by " ) ;
333- msg. push_str ( & describe_path (
334- & cx. parents . path_to_bottom ( & parent. package_id ( ) ) ,
335- ) ) ;
330+ msg. push_str ( & describe_path_in_context ( cx, & parent. package_id ( ) ) ) ;
336331
337332 msg
338333 } ;
@@ -351,12 +346,57 @@ pub(super) fn activation_error(
351346 to_resolve_err ( anyhow:: format_err!( "{}" , msg) )
352347}
353348
349+ /// Returns String representation of dependency chain for a particular `pkgid`
350+ /// within given context.
351+ pub ( super ) fn describe_path_in_context ( cx : & Context , id : & PackageId ) -> String {
352+ let iter = cx
353+ . parents
354+ . path_to_bottom ( id)
355+ . into_iter ( )
356+ . map ( |( p, d) | ( p, d. and_then ( |d| d. iter ( ) . next ( ) ) ) ) ;
357+ describe_path ( iter)
358+ }
359+
354360/// Returns String representation of dependency chain for a particular `pkgid`.
355- pub ( super ) fn describe_path ( path : & [ & PackageId ] ) -> String {
361+ ///
362+ /// Note that all elements of `path` iterator should have `Some` dependency
363+ /// except the first one. It would look like:
364+ ///
365+ /// (pkg0, None)
366+ /// -> (pkg1, dep from pkg1 satisfied by pkg0)
367+ /// -> (pkg2, dep from pkg2 satisfied by pkg1)
368+ /// -> ...
369+ pub ( crate ) fn describe_path < ' a > (
370+ mut path : impl Iterator < Item = ( & ' a PackageId , Option < & ' a Dependency > ) > ,
371+ ) -> String {
356372 use std:: fmt:: Write ;
357- let mut dep_path_desc = format ! ( "package `{}`" , path[ 0 ] ) ;
358- for dep in path[ 1 ..] . iter ( ) {
359- write ! ( dep_path_desc, "\n ... which is depended on by `{}`" , dep) . unwrap ( ) ;
373+
374+ if let Some ( p) = path. next ( ) {
375+ let mut dep_path_desc = format ! ( "package `{}`" , p. 0 ) ;
376+ for ( pkg, dep) in path {
377+ let dep = dep. unwrap ( ) ;
378+ let source_kind = if dep. source_id ( ) . is_path ( ) {
379+ "path "
380+ } else if dep. source_id ( ) . is_git ( ) {
381+ "git "
382+ } else {
383+ ""
384+ } ;
385+ let requirement = if source_kind. is_empty ( ) {
386+ format ! ( "{} = \" {}\" " , dep. name_in_toml( ) , dep. version_req( ) )
387+ } else {
388+ dep. name_in_toml ( ) . to_string ( )
389+ } ;
390+ write ! (
391+ dep_path_desc,
392+ "\n ... which satisfies {}dependency `{}` of package `{}`" ,
393+ source_kind, requirement, pkg
394+ )
395+ . unwrap ( ) ;
396+ }
397+
398+ return dep_path_desc;
360399 }
361- dep_path_desc
400+
401+ String :: new ( )
362402}
0 commit comments