@@ -10,6 +10,17 @@ use crate::util::interning::{InternedString, INTERNED_DEFAULT};
10
10
use crate :: util:: CargoResult ;
11
11
use std:: collections:: { HashMap , HashSet } ;
12
12
13
+ #[ derive( Debug , Copy , Clone , Eq , PartialEq , Hash , Ord , PartialOrd ) ]
14
+ pub struct NodeId {
15
+ index : usize ,
16
+ }
17
+
18
+ impl NodeId {
19
+ fn with_index ( index : usize ) -> Self {
20
+ Self { index }
21
+ }
22
+ }
23
+
13
24
#[ derive( Debug , Clone , Eq , PartialEq , Hash , Ord , PartialOrd ) ]
14
25
pub enum Node {
15
26
Package {
@@ -20,7 +31,7 @@ pub enum Node {
20
31
} ,
21
32
Feature {
22
33
/// Index of the package node this feature is for.
23
- node_index : usize ,
34
+ node_index : NodeId ,
24
35
/// Name of the feature.
25
36
name : InternedString ,
26
37
} ,
@@ -29,15 +40,15 @@ pub enum Node {
29
40
#[ derive( Debug , Copy , Hash , Eq , Clone , PartialEq ) ]
30
41
pub struct Edge {
31
42
kind : EdgeKind ,
32
- node : usize ,
43
+ node : NodeId ,
33
44
}
34
45
35
46
impl Edge {
36
47
pub fn kind ( & self ) -> EdgeKind {
37
48
self . kind
38
49
}
39
50
40
- pub fn node ( & self ) -> usize {
51
+ pub fn node ( & self ) -> NodeId {
41
52
self . node
42
53
}
43
54
}
@@ -94,19 +105,19 @@ pub struct Graph<'a> {
94
105
/// sync.
95
106
edges : Vec < Edges > ,
96
107
/// Index maps a node to an index, for fast lookup.
97
- index : HashMap < Node , usize > ,
108
+ index : HashMap < Node , NodeId > ,
98
109
/// Map for looking up packages.
99
110
package_map : HashMap < PackageId , & ' a Package > ,
100
111
/// Set of indexes of feature nodes that were added via the command-line.
101
112
///
102
113
/// For example `--features foo` will mark the "foo" node here.
103
- cli_features : HashSet < usize > ,
114
+ cli_features : HashSet < NodeId > ,
104
115
/// Map of dependency names, used for building internal feature map for
105
116
/// `dep_name/feat_name` syntax.
106
117
///
107
118
/// Key is the index of a package node, value is a map of `dep_name` to a
108
119
/// set of `(pkg_node_index, is_optional)`.
109
- dep_name_map : HashMap < usize , HashMap < InternedString , HashSet < ( usize , bool ) > > > ,
120
+ dep_name_map : HashMap < NodeId , HashMap < InternedString , HashSet < ( NodeId , bool ) > > > ,
110
121
}
111
122
112
123
impl < ' a > Graph < ' a > {
@@ -122,52 +133,52 @@ impl<'a> Graph<'a> {
122
133
}
123
134
124
135
/// Adds a new node to the graph, returning its new index.
125
- fn add_node ( & mut self , node : Node ) -> usize {
126
- let from_index = self . nodes . len ( ) ;
136
+ fn add_node ( & mut self , node : Node ) -> NodeId {
137
+ let from_index = NodeId :: with_index ( self . nodes . len ( ) ) ;
127
138
self . nodes . push ( node) ;
128
139
self . edges . push ( Edges :: new ( ) ) ;
129
140
self . index . insert ( self . node ( from_index) . clone ( ) , from_index) ;
130
141
from_index
131
142
}
132
143
133
144
/// Returns a list of nodes the given node index points to for the given kind.
134
- pub fn edges_of_kind ( & self , from : usize , kind : & EdgeKind ) -> Vec < Edge > {
145
+ pub fn edges_of_kind ( & self , from : NodeId , kind : & EdgeKind ) -> Vec < Edge > {
135
146
let edges = self . edges ( from) . of_kind ( kind) ;
136
147
// Created a sorted list for consistent output.
137
148
let mut edges = edges. to_owned ( ) ;
138
149
edges. sort_unstable_by ( |a, b| self . node ( a. node ( ) ) . cmp ( & self . node ( b. node ( ) ) ) ) ;
139
150
edges
140
151
}
141
152
142
- fn edges ( & self , from : usize ) -> & Edges {
143
- & self . edges [ from]
153
+ fn edges ( & self , from : NodeId ) -> & Edges {
154
+ & self . edges [ from. index ]
144
155
}
145
156
146
- fn edges_mut ( & mut self , from : usize ) -> & mut Edges {
147
- & mut self . edges [ from]
157
+ fn edges_mut ( & mut self , from : NodeId ) -> & mut Edges {
158
+ & mut self . edges [ from. index ]
148
159
}
149
160
150
161
/// Returns `true` if the given node has any outgoing edges.
151
- pub fn has_outgoing_edges ( & self , index : usize ) -> bool {
162
+ pub fn has_outgoing_edges ( & self , index : NodeId ) -> bool {
152
163
!self . edges ( index) . is_empty ( )
153
164
}
154
165
155
166
/// Gets a node by index.
156
- pub fn node ( & self , index : usize ) -> & Node {
157
- & self . nodes [ index]
167
+ pub fn node ( & self , index : NodeId ) -> & Node {
168
+ & self . nodes [ index. index ]
158
169
}
159
170
160
171
/// Given a slice of `PackageIds`, returns the indexes of all nodes that match.
161
- pub fn indexes_from_ids ( & self , package_ids : & [ PackageId ] ) -> Vec < usize > {
162
- let mut result: Vec < ( & Node , usize ) > = self
172
+ pub fn indexes_from_ids ( & self , package_ids : & [ PackageId ] ) -> Vec < NodeId > {
173
+ let mut result: Vec < ( & Node , NodeId ) > = self
163
174
. nodes
164
175
. iter ( )
165
176
. enumerate ( )
166
177
. filter ( |( _i, node) | match node {
167
178
Node :: Package { package_id, .. } => package_ids. contains ( package_id) ,
168
179
_ => false ,
169
180
} )
170
- . map ( |( i, node) | ( node, i ) )
181
+ . map ( |( i, node) | ( node, NodeId :: with_index ( i ) ) )
171
182
. collect ( ) ;
172
183
// Sort for consistent output (the same command should always return
173
184
// the same output). "unstable" since nodes should always be unique.
@@ -179,7 +190,7 @@ impl<'a> Graph<'a> {
179
190
self . package_map [ & id]
180
191
}
181
192
182
- fn package_id_for_index ( & self , index : usize ) -> PackageId {
193
+ fn package_id_for_index ( & self , index : NodeId ) -> PackageId {
183
194
match self . node ( index) {
184
195
Node :: Package { package_id, .. } => * package_id,
185
196
Node :: Feature { .. } => panic ! ( "unexpected feature node" ) ,
@@ -188,32 +199,32 @@ impl<'a> Graph<'a> {
188
199
189
200
/// Returns `true` if the given feature node index is a feature enabled
190
201
/// via the command-line.
191
- pub fn is_cli_feature ( & self , index : usize ) -> bool {
202
+ pub fn is_cli_feature ( & self , index : NodeId ) -> bool {
192
203
self . cli_features . contains ( & index)
193
204
}
194
205
195
206
/// Returns a new graph by removing all nodes not reachable from the
196
207
/// given nodes.
197
- pub fn from_reachable ( & self , roots : & [ usize ] ) -> Graph < ' a > {
208
+ pub fn from_reachable ( & self , roots : & [ NodeId ] ) -> Graph < ' a > {
198
209
// Graph built with features does not (yet) support --duplicates.
199
210
assert ! ( self . dep_name_map. is_empty( ) ) ;
200
211
let mut new_graph = Graph :: new ( self . package_map . clone ( ) ) ;
201
212
// Maps old index to new index. None if not yet visited.
202
- let mut remap: Vec < Option < usize > > = vec ! [ None ; self . nodes. len( ) ] ;
213
+ let mut remap: Vec < Option < NodeId > > = vec ! [ None ; self . nodes. len( ) ] ;
203
214
204
215
fn visit (
205
216
graph : & Graph < ' _ > ,
206
217
new_graph : & mut Graph < ' _ > ,
207
- remap : & mut Vec < Option < usize > > ,
208
- index : usize ,
209
- ) -> usize {
210
- if let Some ( new_index) = remap[ index] {
218
+ remap : & mut Vec < Option < NodeId > > ,
219
+ index : NodeId ,
220
+ ) -> NodeId {
221
+ if let Some ( new_index) = remap[ index. index ] {
211
222
// Already visited.
212
223
return new_index;
213
224
}
214
225
let node = graph. node ( index) . clone ( ) ;
215
226
let new_from = new_graph. add_node ( node) ;
216
- remap[ index] = Some ( new_from) ;
227
+ remap[ index. index ] = Some ( new_from) ;
217
228
// Visit dependencies.
218
229
for edge in graph. edges ( index) . all ( ) {
219
230
let new_to_index = visit ( graph, new_graph, remap, edge. node ( ) ) ;
@@ -241,32 +252,32 @@ impl<'a> Graph<'a> {
241
252
for edge in node_edges. all ( ) {
242
253
let new_edge = Edge {
243
254
kind : edge. kind ( ) ,
244
- node : from_idx,
255
+ node : NodeId :: with_index ( from_idx) ,
245
256
} ;
246
- new_edges[ edge. node ( ) ] . add_edge ( new_edge) ;
257
+ new_edges[ edge. node ( ) . index ] . add_edge ( new_edge) ;
247
258
}
248
259
}
249
260
self . edges = new_edges;
250
261
}
251
262
252
263
/// Returns a list of nodes that are considered "duplicates" (same package
253
264
/// name, with different versions/features/source/etc.).
254
- pub fn find_duplicates ( & self ) -> Vec < usize > {
265
+ pub fn find_duplicates ( & self ) -> Vec < NodeId > {
255
266
// Graph built with features does not (yet) support --duplicates.
256
267
assert ! ( self . dep_name_map. is_empty( ) ) ;
257
268
258
- // Collect a map of package name to Vec<(&Node, usize )>.
269
+ // Collect a map of package name to Vec<(&Node, NodeId )>.
259
270
let mut packages = HashMap :: new ( ) ;
260
271
for ( i, node) in self . nodes . iter ( ) . enumerate ( ) {
261
272
if let Node :: Package { package_id, .. } = node {
262
273
packages
263
274
. entry ( package_id. name ( ) )
264
275
. or_insert_with ( Vec :: new)
265
- . push ( ( node, i ) ) ;
276
+ . push ( ( node, NodeId :: with_index ( i ) ) ) ;
266
277
}
267
278
}
268
279
269
- let mut dupes: Vec < ( & Node , usize ) > = packages
280
+ let mut dupes: Vec < ( & Node , NodeId ) > = packages
270
281
. into_iter ( )
271
282
. filter ( |( _name, indexes) | {
272
283
indexes
@@ -356,7 +367,7 @@ fn add_pkg(
356
367
target_data : & RustcTargetData < ' _ > ,
357
368
requested_kind : CompileKind ,
358
369
opts : & TreeOptions ,
359
- ) -> usize {
370
+ ) -> NodeId {
360
371
let node_features = resolved_features. activated_features ( package_id, features_for) ;
361
372
let node_kind = match features_for {
362
373
FeaturesFor :: HostDep => CompileKind :: Host ,
@@ -373,7 +384,7 @@ fn add_pkg(
373
384
}
374
385
let from_index = graph. add_node ( node) ;
375
386
// Compute the dep name map which is later used for foo/bar feature lookups.
376
- let mut dep_name_map: HashMap < InternedString , HashSet < ( usize , bool ) > > = HashMap :: new ( ) ;
387
+ let mut dep_name_map: HashMap < InternedString , HashSet < ( NodeId , bool ) > > = HashMap :: new ( ) ;
377
388
let mut deps: Vec < _ > = resolve. deps ( package_id) . collect ( ) ;
378
389
deps. sort_unstable_by_key ( |( dep_id, _) | * dep_id) ;
379
390
let show_all_targets = opts. target == super :: Target :: All ;
@@ -512,9 +523,9 @@ fn add_pkg(
512
523
fn add_feature (
513
524
graph : & mut Graph < ' _ > ,
514
525
name : InternedString ,
515
- from : Option < usize > ,
526
+ from : Option < NodeId > ,
516
527
to : Edge ,
517
- ) -> ( bool , usize ) {
528
+ ) -> ( bool , NodeId ) {
518
529
// `to` *must* point to a package node.
519
530
assert ! ( matches! { graph. node( to. node( ) ) , Node :: Package { ..} } ) ;
520
531
let node = Node :: Feature {
@@ -547,7 +558,7 @@ fn add_feature(
547
558
/// `--invert`.
548
559
fn add_cli_features (
549
560
graph : & mut Graph < ' _ > ,
550
- package_index : usize ,
561
+ package_index : NodeId ,
551
562
cli_features : & CliFeatures ,
552
563
feature_map : & FeatureMap ,
553
564
) {
@@ -596,7 +607,7 @@ fn add_cli_features(
596
607
"missing dep graph connection for CLI feature `{}` for member {:?}\n \
597
608
Please file a bug report at https://github.com/rust-lang/cargo/issues",
598
609
fv,
599
- graph. nodes. get( package_index)
610
+ graph. nodes. get( package_index. index )
600
611
) ;
601
612
}
602
613
} ;
@@ -626,15 +637,15 @@ fn add_cli_features(
626
637
/// for every package.
627
638
fn add_internal_features ( graph : & mut Graph < ' _ > , resolve : & Resolve ) {
628
639
// Collect features already activated by dependencies or command-line.
629
- let feature_nodes: Vec < ( PackageId , usize , usize , InternedString ) > = graph
640
+ let feature_nodes: Vec < ( PackageId , NodeId , NodeId , InternedString ) > = graph
630
641
. nodes
631
642
. iter ( )
632
643
. enumerate ( )
633
644
. filter_map ( |( i, node) | match node {
634
645
Node :: Package { .. } => None ,
635
646
Node :: Feature { node_index, name } => {
636
647
let package_id = graph. package_id_for_index ( * node_index) ;
637
- Some ( ( package_id, * node_index, i , * name) )
648
+ Some ( ( package_id, * node_index, NodeId :: with_index ( i ) , * name) )
638
649
}
639
650
} )
640
651
. collect ( ) ;
@@ -660,8 +671,8 @@ fn add_feature_rec(
660
671
resolve : & Resolve ,
661
672
feature_name : InternedString ,
662
673
package_id : PackageId ,
663
- from : usize ,
664
- package_index : usize ,
674
+ from : NodeId ,
675
+ package_index : NodeId ,
665
676
) {
666
677
let feature_map = resolve. summary ( package_id) . features ( ) ;
667
678
let Some ( fvs) = feature_map. get ( & feature_name) else {
0 commit comments