1use super::TreeOptions;
4use crate::core::compiler::{CompileKind, RustcTargetData};
5use crate::core::dependency::DepKind;
6use crate::core::resolver::Resolve;
7use crate::core::resolver::features::{CliFeatures, FeaturesFor, ResolvedFeatures};
8use crate::core::{FeatureMap, FeatureValue, Package, PackageId, PackageIdSpec, Workspace};
9use crate::util::CargoResult;
10use crate::util::interning::{INTERNED_DEFAULT, InternedString};
11use std::collections::{HashMap, HashSet};
12
13#[derive(Debug, Copy, Clone)]
14pub struct NodeId {
15 index: usize,
16 #[allow(dead_code)] debug: InternedString,
18}
19
20impl NodeId {
21 fn new(index: usize, debug: InternedString) -> Self {
22 Self { index, debug }
23 }
24}
25
26impl PartialEq for NodeId {
27 fn eq(&self, other: &Self) -> bool {
28 self.index == other.index
29 }
30}
31
32impl Eq for NodeId {}
33
34impl PartialOrd for NodeId {
35 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
36 Some(self.cmp(other))
37 }
38}
39
40impl Ord for NodeId {
41 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
42 self.index.cmp(&other.index)
43 }
44}
45
46impl std::hash::Hash for NodeId {
47 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
48 self.index.hash(state)
49 }
50}
51
52#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
53pub enum Node {
54 Package {
55 package_id: PackageId,
56 features: Vec<InternedString>,
58 kind: CompileKind,
59 },
60 Feature {
61 node_index: NodeId,
63 name: InternedString,
65 },
66}
67
68impl Node {
69 fn name(&self) -> InternedString {
70 match self {
71 Self::Package { package_id, .. } => package_id.name(),
72 Self::Feature { name, .. } => *name,
73 }
74 }
75}
76
77#[derive(Debug, Copy, Hash, Eq, Clone, PartialEq)]
78pub struct Edge {
79 kind: EdgeKind,
80 node: NodeId,
81 public: bool,
82}
83
84impl Edge {
85 pub fn kind(&self) -> EdgeKind {
86 self.kind
87 }
88
89 pub fn node(&self) -> NodeId {
90 self.node
91 }
92
93 pub fn public(&self) -> bool {
94 self.public
95 }
96}
97
98#[derive(Debug, Copy, Hash, Eq, Clone, PartialEq)]
100pub enum EdgeKind {
101 Dep(DepKind),
102 Feature,
103}
104
105#[derive(Clone, Debug)]
114struct Edges(HashMap<EdgeKind, Vec<Edge>>);
115
116impl Edges {
117 fn new() -> Edges {
118 Edges(HashMap::new())
119 }
120
121 fn add_edge(&mut self, edge: Edge) {
123 let indexes = self.0.entry(edge.kind()).or_default();
124 if !indexes.contains(&edge) {
125 indexes.push(edge)
126 }
127 }
128
129 fn all(&self) -> impl Iterator<Item = &Edge> + '_ {
130 self.0.values().flatten()
131 }
132
133 fn of_kind(&self, kind: &EdgeKind) -> &[Edge] {
134 self.0.get(kind).map(Vec::as_slice).unwrap_or_default()
135 }
136
137 fn is_empty(&self) -> bool {
138 self.0.is_empty()
139 }
140}
141
142#[derive(Debug)]
144pub struct Graph<'a> {
145 nodes: Vec<Node>,
146 edges: Vec<Edges>,
150 index: HashMap<Node, NodeId>,
152 package_map: HashMap<PackageId, &'a Package>,
154 cli_features: HashSet<NodeId>,
158 dep_name_map: HashMap<NodeId, HashMap<InternedString, HashSet<(NodeId, bool)>>>,
164}
165
166impl<'a> Graph<'a> {
167 fn new(package_map: HashMap<PackageId, &'a Package>) -> Graph<'a> {
168 Graph {
169 nodes: Vec::new(),
170 edges: Vec::new(),
171 index: HashMap::new(),
172 package_map,
173 cli_features: HashSet::new(),
174 dep_name_map: HashMap::new(),
175 }
176 }
177
178 fn add_node(&mut self, node: Node) -> NodeId {
180 let from_index = NodeId::new(self.nodes.len(), node.name());
181 self.nodes.push(node);
182 self.edges.push(Edges::new());
183 self.index.insert(self.node(from_index).clone(), from_index);
184 from_index
185 }
186
187 pub fn edges_of_kind(&self, from: NodeId, kind: &EdgeKind) -> Vec<Edge> {
189 let edges = self.edges(from).of_kind(kind);
190 let mut edges = edges.to_owned();
192 edges.sort_unstable_by(|a, b| self.node(a.node()).cmp(&self.node(b.node())));
193 edges
194 }
195
196 fn edges(&self, from: NodeId) -> &Edges {
197 &self.edges[from.index]
198 }
199
200 fn edges_mut(&mut self, from: NodeId) -> &mut Edges {
201 &mut self.edges[from.index]
202 }
203
204 pub fn has_outgoing_edges(&self, index: NodeId) -> bool {
206 !self.edges(index).is_empty()
207 }
208
209 pub fn node(&self, index: NodeId) -> &Node {
211 &self.nodes[index.index]
212 }
213
214 pub fn indexes_from_ids(&self, package_ids: &[PackageId]) -> Vec<NodeId> {
216 let mut result: Vec<(&Node, NodeId)> = self
217 .nodes
218 .iter()
219 .enumerate()
220 .filter(|(_i, node)| match node {
221 Node::Package { package_id, .. } => package_ids.contains(package_id),
222 _ => false,
223 })
224 .map(|(i, node)| (node, NodeId::new(i, node.name())))
225 .collect();
226 result.sort_unstable();
229 result.into_iter().map(|(_node, i)| i).collect()
230 }
231
232 pub fn package_for_id(&self, id: PackageId) -> &Package {
233 self.package_map[&id]
234 }
235
236 fn package_id_for_index(&self, index: NodeId) -> PackageId {
237 match self.node(index) {
238 Node::Package { package_id, .. } => *package_id,
239 Node::Feature { .. } => panic!("unexpected feature node"),
240 }
241 }
242
243 pub fn is_cli_feature(&self, index: NodeId) -> bool {
246 self.cli_features.contains(&index)
247 }
248
249 pub fn from_reachable(&self, roots: &[NodeId]) -> Graph<'a> {
252 assert!(self.dep_name_map.is_empty());
254 let mut new_graph = Graph::new(self.package_map.clone());
255 let mut remap: Vec<Option<NodeId>> = vec![None; self.nodes.len()];
257
258 fn visit(
259 graph: &Graph<'_>,
260 new_graph: &mut Graph<'_>,
261 remap: &mut Vec<Option<NodeId>>,
262 index: NodeId,
263 ) -> NodeId {
264 if let Some(new_index) = remap[index.index] {
265 return new_index;
267 }
268 let node = graph.node(index).clone();
269 let new_from = new_graph.add_node(node);
270 remap[index.index] = Some(new_from);
271 for edge in graph.edges(index).all() {
273 let new_to_index = visit(graph, new_graph, remap, edge.node());
274 let new_edge = Edge {
275 kind: edge.kind(),
276 node: new_to_index,
277 public: edge.public(),
278 };
279 new_graph.edges_mut(new_from).add_edge(new_edge);
280 }
281 new_from
282 }
283
284 for root in roots {
286 visit(self, &mut new_graph, &mut remap, *root);
287 }
288
289 new_graph
290 }
291
292 pub fn invert(&mut self) {
294 let mut new_edges = vec![Edges::new(); self.edges.len()];
295 for (from_idx, node_edges) in self.edges.iter().enumerate() {
296 for edge in node_edges.all() {
297 let new_edge = Edge {
298 kind: edge.kind(),
299 node: NodeId::new(from_idx, self.nodes[from_idx].name()),
300 public: edge.public(),
301 };
302 new_edges[edge.node().index].add_edge(new_edge);
303 }
304 }
305 self.edges = new_edges;
306 }
307
308 pub fn find_duplicates(&self) -> Vec<NodeId> {
311 assert!(self.dep_name_map.is_empty());
313
314 let mut packages = HashMap::new();
316 for (i, node) in self.nodes.iter().enumerate() {
317 if let Node::Package { package_id, .. } = node {
318 packages
319 .entry(package_id.name())
320 .or_insert_with(Vec::new)
321 .push((node, NodeId::new(i, node.name())));
322 }
323 }
324
325 let mut dupes: Vec<(&Node, NodeId)> = packages
326 .into_iter()
327 .filter(|(_name, indexes)| {
328 indexes
329 .into_iter()
330 .map(|(node, _)| {
331 match node {
332 Node::Package {
333 package_id,
334 features,
335 ..
336 } => {
337 Node::Package {
339 package_id: package_id.clone(),
340 features: features.clone(),
341 kind: CompileKind::Host,
342 }
343 }
344 _ => unreachable!(),
345 }
346 })
347 .collect::<HashSet<_>>()
348 .len()
349 > 1
350 })
351 .flat_map(|(_name, indexes)| indexes)
352 .collect();
353
354 dupes.sort_unstable();
356 dupes.into_iter().map(|(_node, i)| i).collect()
357 }
358}
359
360pub fn build<'a>(
362 ws: &Workspace<'_>,
363 resolve: &Resolve,
364 resolved_features: &ResolvedFeatures,
365 specs: &[PackageIdSpec],
366 cli_features: &CliFeatures,
367 target_data: &RustcTargetData<'_>,
368 requested_kinds: &[CompileKind],
369 package_map: HashMap<PackageId, &'a Package>,
370 opts: &TreeOptions,
371) -> CargoResult<Graph<'a>> {
372 let mut graph = Graph::new(package_map);
373 let mut members_with_features = ws.members_with_features(specs, cli_features)?;
374 members_with_features.sort_unstable_by_key(|(member, _)| member.package_id());
375 for (member, cli_features) in members_with_features {
376 let member_id = member.package_id();
377 let features_for = FeaturesFor::from_for_host(member.proc_macro());
378 for kind in requested_kinds {
379 let member_index = add_pkg(
380 &mut graph,
381 resolve,
382 resolved_features,
383 member_id,
384 features_for,
385 target_data,
386 *kind,
387 opts,
388 );
389 if opts.graph_features {
390 let fmap = resolve.summary(member_id).features();
391 add_cli_features(&mut graph, member_index, &cli_features, fmap);
392 }
393 }
394 }
395 if opts.graph_features {
396 add_internal_features(&mut graph, resolve);
397 }
398 Ok(graph)
399}
400
401fn add_pkg(
407 graph: &mut Graph<'_>,
408 resolve: &Resolve,
409 resolved_features: &ResolvedFeatures,
410 package_id: PackageId,
411 features_for: FeaturesFor,
412 target_data: &RustcTargetData<'_>,
413 requested_kind: CompileKind,
414 opts: &TreeOptions,
415) -> NodeId {
416 let node_features = resolved_features.activated_features(package_id, features_for);
417 let node_kind = match features_for {
418 FeaturesFor::HostDep => CompileKind::Host,
419 FeaturesFor::ArtifactDep(target) => CompileKind::Target(target),
420 FeaturesFor::NormalOrDev => requested_kind,
421 };
422 let node = Node::Package {
423 package_id,
424 features: node_features,
425 kind: node_kind,
426 };
427 if let Some(idx) = graph.index.get(&node) {
428 return *idx;
429 }
430 let from_index = graph.add_node(node);
431 let mut dep_name_map: HashMap<InternedString, HashSet<(NodeId, bool)>> = HashMap::new();
433 let mut deps: Vec<_> = resolve.deps(package_id).collect();
434 deps.sort_unstable_by_key(|(dep_id, _)| *dep_id);
435 let show_all_targets = opts.target == super::Target::All;
436 for (dep_id, deps) in deps {
437 let mut deps: Vec<_> = deps
438 .iter()
439 .filter(|dep| {
442 let kind = match (node_kind, dep.kind()) {
443 (CompileKind::Host, _) => CompileKind::Host,
444 (_, DepKind::Build) => CompileKind::Host,
445 (_, DepKind::Normal) => node_kind,
446 (_, DepKind::Development) => node_kind,
447 };
448 if !show_all_targets && !target_data.dep_platform_activated(dep, kind) {
450 return false;
451 }
452 if !opts.edge_kinds.contains(&EdgeKind::Dep(dep.kind())) {
454 return false;
455 }
456 if opts.no_proc_macro && graph.package_for_id(dep_id).proc_macro() {
458 return false;
459 }
460 if dep.is_optional() {
461 if !resolved_features.is_dep_activated(
464 package_id,
465 features_for,
466 dep.name_in_toml(),
467 ) {
468 return false;
469 }
470 }
471 true
472 })
473 .collect();
474
475 if deps.is_empty() {
478 continue;
479 }
480
481 deps.sort_unstable_by_key(|dep| (dep.kind(), dep.name_in_toml()));
482 let dep_pkg = graph.package_map[&dep_id];
483
484 for dep in deps {
485 let dep_features_for = match dep
486 .artifact()
487 .and_then(|artifact| artifact.target())
488 .and_then(|target| target.to_resolved_compile_target(requested_kind))
489 {
490 Some(target) => FeaturesFor::ArtifactDep(target),
492 None if features_for != FeaturesFor::default() => features_for,
500 None => {
505 if dep.is_build() || dep_pkg.proc_macro() {
506 FeaturesFor::HostDep
507 } else {
508 features_for
509 }
510 }
511 };
512 let dep_index = add_pkg(
513 graph,
514 resolve,
515 resolved_features,
516 dep_id,
517 dep_features_for,
518 target_data,
519 requested_kind,
520 opts,
521 );
522 let new_edge = Edge {
523 kind: EdgeKind::Dep(dep.kind()),
524 node: dep_index,
525 public: dep.is_public(),
526 };
527 if opts.graph_features {
528 dep_name_map
530 .entry(dep.name_in_toml())
531 .or_default()
532 .insert((dep_index, dep.is_optional()));
533 if dep.uses_default_features() {
534 add_feature(graph, INTERNED_DEFAULT, Some(from_index), new_edge);
535 }
536 for feature in dep.features().iter() {
537 add_feature(graph, *feature, Some(from_index), new_edge);
538 }
539 if !dep.uses_default_features() && dep.features().is_empty() {
540 graph.edges_mut(from_index).add_edge(new_edge);
542 }
543 } else {
544 graph.edges_mut(from_index).add_edge(new_edge);
545 }
546 }
547 }
548 if opts.graph_features {
549 assert!(
550 graph
551 .dep_name_map
552 .insert(from_index, dep_name_map)
553 .is_none()
554 );
555 }
556
557 from_index
558}
559
560fn add_feature(
572 graph: &mut Graph<'_>,
573 name: InternedString,
574 from: Option<NodeId>,
575 to: Edge,
576) -> (bool, NodeId) {
577 assert!(matches! {graph.node(to.node()), Node::Package{..}});
579 let node = Node::Feature {
580 node_index: to.node(),
581 name,
582 };
583 let (missing, node_index) = match graph.index.get(&node) {
584 Some(idx) => (false, *idx),
585 None => (true, graph.add_node(node)),
586 };
587 if let Some(from) = from {
588 let from_edge = Edge {
589 kind: to.kind(),
590 node: node_index,
591 public: to.public(),
592 };
593 graph.edges_mut(from).add_edge(from_edge);
594 }
595 let to_edge = Edge {
596 kind: EdgeKind::Feature,
597 node: to.node(),
598 public: true,
599 };
600 graph.edges_mut(node_index).add_edge(to_edge);
601 (missing, node_index)
602}
603
604fn add_cli_features(
610 graph: &mut Graph<'_>,
611 package_index: NodeId,
612 cli_features: &CliFeatures,
613 feature_map: &FeatureMap,
614) {
615 let mut to_add: HashSet<FeatureValue> = HashSet::new();
620 if cli_features.all_features {
621 to_add.extend(feature_map.keys().map(|feat| FeatureValue::Feature(*feat)));
622 }
623
624 if cli_features.uses_default_features {
625 to_add.insert(FeatureValue::Feature(INTERNED_DEFAULT));
626 }
627 to_add.extend(cli_features.features.iter().cloned());
628
629 for fv in to_add {
631 match fv {
632 FeatureValue::Feature(feature) => {
633 let feature_edge = Edge {
634 kind: EdgeKind::Feature,
635 node: package_index,
636 public: true,
637 };
638 let index = add_feature(graph, feature, None, feature_edge).1;
639 graph.cli_features.insert(index);
640 }
641 FeatureValue::Dep { .. } => panic!("unexpected cli dep feature {}", fv),
643 FeatureValue::DepFeature {
644 dep_name,
645 dep_feature,
646 weak,
647 } => {
648 let dep_connections = match graph.dep_name_map[&package_index].get(&dep_name) {
649 Some(dep_connections) => dep_connections.clone(),
651 None => {
652 if weak {
655 continue;
656 }
657 panic!(
658 "missing dep graph connection for CLI feature `{}` for member {:?}\n\
659 Please file a bug report at https://github.com/rust-lang/cargo/issues",
660 fv,
661 graph.nodes.get(package_index.index)
662 );
663 }
664 };
665 for (dep_index, is_optional) in dep_connections {
666 if is_optional {
667 let feature_edge = Edge {
669 kind: EdgeKind::Feature,
670 node: package_index,
671 public: true,
672 };
673 let index = add_feature(graph, dep_name, None, feature_edge).1;
674 graph.cli_features.insert(index);
675 }
676 let dep_edge = Edge {
677 kind: EdgeKind::Feature,
678 node: dep_index,
679 public: true,
680 };
681 let index = add_feature(graph, dep_feature, None, dep_edge).1;
682 graph.cli_features.insert(index);
683 }
684 }
685 }
686 }
687}
688
689fn add_internal_features(graph: &mut Graph<'_>, resolve: &Resolve) {
692 let feature_nodes: Vec<(PackageId, NodeId, NodeId, InternedString)> = graph
694 .nodes
695 .iter()
696 .enumerate()
697 .filter_map(|(i, node)| match node {
698 Node::Package { .. } => None,
699 Node::Feature { node_index, name } => {
700 let package_id = graph.package_id_for_index(*node_index);
701 Some((package_id, *node_index, NodeId::new(i, *name), *name))
702 }
703 })
704 .collect();
705
706 for (package_id, package_index, feature_index, feature_name) in feature_nodes {
707 add_feature_rec(
708 graph,
709 resolve,
710 feature_name,
711 package_id,
712 feature_index,
713 package_index,
714 );
715 }
716}
717
718fn add_feature_rec(
723 graph: &mut Graph<'_>,
724 resolve: &Resolve,
725 feature_name: InternedString,
726 package_id: PackageId,
727 from: NodeId,
728 package_index: NodeId,
729) {
730 let feature_map = resolve.summary(package_id).features();
731 let Some(fvs) = feature_map.get(&feature_name) else {
732 return;
733 };
734 for fv in fvs {
735 match fv {
736 FeatureValue::Feature(dep_name) => {
737 let feature_edge = Edge {
738 kind: EdgeKind::Feature,
739 node: package_index,
740 public: true,
741 };
742 let (missing, feat_index) = add_feature(graph, *dep_name, Some(from), feature_edge);
743 if missing {
745 add_feature_rec(
746 graph,
747 resolve,
748 *dep_name,
749 package_id,
750 feat_index,
751 package_index,
752 );
753 }
754 }
755 FeatureValue::Dep { .. } => {}
760 FeatureValue::DepFeature {
761 dep_name,
762 dep_feature,
763 weak,
769 } => {
770 let dep_indexes = match graph.dep_name_map[&package_index].get(dep_name) {
771 Some(indexes) => indexes.clone(),
772 None => {
773 tracing::debug!(
774 "enabling feature {} on {}, found {}/{}, \
775 dep appears to not be enabled",
776 feature_name,
777 package_id,
778 dep_name,
779 dep_feature
780 );
781 continue;
782 }
783 };
784 for (dep_index, is_optional) in dep_indexes {
785 let dep_pkg_id = graph.package_id_for_index(dep_index);
786 if is_optional && !weak {
787 let feature_edge = Edge {
789 kind: EdgeKind::Feature,
790 node: package_index,
791 public: true,
792 };
793 add_feature(graph, *dep_name, Some(from), feature_edge);
794 }
795 let dep_edge = Edge {
796 kind: EdgeKind::Feature,
797 node: dep_index,
798 public: true,
799 };
800 let (missing, feat_index) =
801 add_feature(graph, *dep_feature, Some(from), dep_edge);
802 if missing {
803 add_feature_rec(
804 graph,
805 resolve,
806 *dep_feature,
807 dep_pkg_id,
808 feat_index,
809 dep_index,
810 );
811 }
812 }
813 }
814 }
815 }
816}