@@ -82,6 +82,7 @@ pub(super) fn activation_error(
82
82
cx. parents
83
83
. path_to_bottom ( & parent. package_id ( ) )
84
84
. into_iter ( )
85
+ . map ( |( node, _) | node)
85
86
. cloned ( )
86
87
. collect ( ) ,
87
88
)
@@ -90,9 +91,7 @@ pub(super) fn activation_error(
90
91
if !candidates. is_empty ( ) {
91
92
let mut msg = format ! ( "failed to select a version for `{}`." , dep. package_name( ) ) ;
92
93
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 ( ) ) ) ;
96
95
97
96
msg. push_str ( "\n versions that meet the requirements `" ) ;
98
97
msg. push_str ( & dep. version_req ( ) . to_string ( ) ) ;
@@ -128,7 +127,7 @@ pub(super) fn activation_error(
128
127
msg. push_str ( "`, but it conflicts with a previous package which links to `" ) ;
129
128
msg. push_str ( link) ;
130
129
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 ) ) ;
132
131
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. " ) ;
133
132
msg. push_str ( "Try to adjust your dependencies so that only one package uses the links ='" ) ;
134
133
msg. push_str ( & * dep. package_name ( ) ) ;
@@ -197,7 +196,7 @@ pub(super) fn activation_error(
197
196
for ( p, r) in & conflicting_activations {
198
197
if let ConflictReason :: Semver = r {
199
198
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 ) ) ;
201
200
}
202
201
}
203
202
}
@@ -250,9 +249,7 @@ pub(super) fn activation_error(
250
249
registry. describe_source( dep. source_id( ) ) ,
251
250
) ;
252
251
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 ( ) ) ) ;
256
253
257
254
// If we have a path dependency with a locked version, then this may
258
255
// indicate that we updated a sub-package and forgot to run `cargo
@@ -330,9 +327,7 @@ pub(super) fn activation_error(
330
327
}
331
328
msg. push_str ( & format ! ( "location searched: {}\n " , dep. source_id( ) ) ) ;
332
329
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 ( ) ) ) ;
336
331
337
332
msg
338
333
} ;
@@ -351,12 +346,57 @@ pub(super) fn activation_error(
351
346
to_resolve_err ( anyhow:: format_err!( "{}" , msg) )
352
347
}
353
348
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
+
354
360
/// 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 {
356
372
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;
360
399
}
361
- dep_path_desc
400
+
401
+ String :: new ( )
362
402
}
0 commit comments