47
47
//! that we're implementing something that probably shouldn't be allocating all
48
48
//! over the place.
49
49
50
- use std:: collections:: { BTreeMap , BTreeSet , HashMap , HashSet } ;
50
+ use std:: collections:: { BTreeMap , HashMap , HashSet } ;
51
51
use std:: mem;
52
52
use std:: rc:: Rc ;
53
53
use std:: time:: { Duration , Instant } ;
@@ -1007,13 +1007,15 @@ fn check_cycles(resolve: &Resolve) -> CargoResult<()> {
1007
1007
// dev-dependency since that doesn't count for cycles.
1008
1008
let mut graph = BTreeMap :: new ( ) ;
1009
1009
for id in resolve. iter ( ) {
1010
- let set = graph. entry ( id) . or_insert_with ( BTreeSet :: new) ;
1011
- for ( dep, listings) in resolve. deps_not_replaced ( id) {
1012
- let is_transitive = listings. iter ( ) . any ( |d| d. is_transitive ( ) ) ;
1013
-
1014
- if is_transitive {
1015
- set. insert ( dep) ;
1016
- set. extend ( resolve. replacement ( dep) ) ;
1010
+ let map = graph. entry ( id) . or_insert_with ( BTreeMap :: new) ;
1011
+ for ( dep_id, listings) in resolve. deps_not_replaced ( id) {
1012
+ let transitive_dep = listings. iter ( ) . find ( |d| d. is_transitive ( ) ) ;
1013
+
1014
+ if let Some ( transitive_dep) = transitive_dep. cloned ( ) {
1015
+ map. insert ( dep_id, transitive_dep. clone ( ) ) ;
1016
+ resolve
1017
+ . replacement ( dep_id)
1018
+ . map ( |p| map. insert ( p, transitive_dep) ) ;
1017
1019
}
1018
1020
}
1019
1021
}
@@ -1033,23 +1035,29 @@ fn check_cycles(resolve: &Resolve) -> CargoResult<()> {
1033
1035
return Ok ( ( ) ) ;
1034
1036
1035
1037
fn visit (
1036
- graph : & BTreeMap < PackageId , BTreeSet < PackageId > > ,
1038
+ graph : & BTreeMap < PackageId , BTreeMap < PackageId , Dependency > > ,
1037
1039
id : PackageId ,
1038
1040
visited : & mut HashSet < PackageId > ,
1039
1041
path : & mut Vec < PackageId > ,
1040
1042
checked : & mut HashSet < PackageId > ,
1041
1043
) -> CargoResult < ( ) > {
1042
1044
path. push ( id) ;
1043
1045
if !visited. insert ( id) {
1046
+ let iter = path. iter ( ) . rev ( ) . skip ( 1 ) . scan ( id, |child, parent| {
1047
+ let dep = graph. get ( parent) . and_then ( |adjacent| adjacent. get ( child) ) ;
1048
+ * child = * parent;
1049
+ Some ( ( parent, dep) )
1050
+ } ) ;
1051
+ let iter = std:: iter:: once ( ( & id, None ) ) . chain ( iter) ;
1044
1052
anyhow:: bail!(
1045
1053
"cyclic package dependency: package `{}` depends on itself. Cycle:\n {}" ,
1046
1054
id,
1047
- errors:: describe_path( & path . iter( ) . rev ( ) . collect :: < Vec <_>> ( ) ) ,
1055
+ errors:: describe_path( iter) ,
1048
1056
) ;
1049
1057
}
1050
1058
1051
1059
if checked. insert ( id) {
1052
- for dep in graph[ & id] . iter ( ) {
1060
+ for dep in graph[ & id] . keys ( ) {
1053
1061
visit ( graph, * dep, visited, path, checked) ?;
1054
1062
}
1055
1063
}
0 commit comments