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 opts.public && !dep.is_public() {
462 return false;
463 }
464 if dep.is_optional() {
465 if !resolved_features.is_dep_activated(
468 package_id,
469 features_for,
470 dep.name_in_toml(),
471 ) {
472 return false;
473 }
474 }
475 true
476 })
477 .collect();
478
479 if deps.is_empty() {
482 continue;
483 }
484
485 deps.sort_unstable_by_key(|dep| (dep.kind(), dep.name_in_toml()));
486 let dep_pkg = graph.package_map[&dep_id];
487
488 for dep in deps {
489 let dep_features_for = match dep
490 .artifact()
491 .and_then(|artifact| artifact.target())
492 .and_then(|target| target.to_resolved_compile_target(requested_kind))
493 {
494 Some(target) => FeaturesFor::ArtifactDep(target),
496 None if features_for != FeaturesFor::default() => features_for,
504 None => {
509 if dep.is_build() || dep_pkg.proc_macro() {
510 FeaturesFor::HostDep
511 } else {
512 features_for
513 }
514 }
515 };
516 let dep_index = add_pkg(
517 graph,
518 resolve,
519 resolved_features,
520 dep_id,
521 dep_features_for,
522 target_data,
523 requested_kind,
524 opts,
525 );
526 let new_edge = Edge {
527 kind: EdgeKind::Dep(dep.kind()),
528 node: dep_index,
529 public: dep.is_public(),
530 };
531 if opts.graph_features {
532 dep_name_map
534 .entry(dep.name_in_toml())
535 .or_default()
536 .insert((dep_index, dep.is_optional()));
537 if dep.uses_default_features() {
538 add_feature(graph, INTERNED_DEFAULT, Some(from_index), new_edge);
539 }
540 for feature in dep.features().iter() {
541 add_feature(graph, *feature, Some(from_index), new_edge);
542 }
543 if !dep.uses_default_features() && dep.features().is_empty() {
544 graph.edges_mut(from_index).add_edge(new_edge);
546 }
547 } else {
548 graph.edges_mut(from_index).add_edge(new_edge);
549 }
550 }
551 }
552 if opts.graph_features {
553 assert!(
554 graph
555 .dep_name_map
556 .insert(from_index, dep_name_map)
557 .is_none()
558 );
559 }
560
561 from_index
562}
563
564fn add_feature(
576 graph: &mut Graph<'_>,
577 name: InternedString,
578 from: Option<NodeId>,
579 to: Edge,
580) -> (bool, NodeId) {
581 assert!(matches! {graph.node(to.node()), Node::Package{..}});
583 let node = Node::Feature {
584 node_index: to.node(),
585 name,
586 };
587 let (missing, node_index) = match graph.index.get(&node) {
588 Some(idx) => (false, *idx),
589 None => (true, graph.add_node(node)),
590 };
591 if let Some(from) = from {
592 let from_edge = Edge {
593 kind: to.kind(),
594 node: node_index,
595 public: to.public(),
596 };
597 graph.edges_mut(from).add_edge(from_edge);
598 }
599 let to_edge = Edge {
600 kind: EdgeKind::Feature,
601 node: to.node(),
602 public: true,
603 };
604 graph.edges_mut(node_index).add_edge(to_edge);
605 (missing, node_index)
606}
607
608fn add_cli_features(
614 graph: &mut Graph<'_>,
615 package_index: NodeId,
616 cli_features: &CliFeatures,
617 feature_map: &FeatureMap,
618) {
619 let mut to_add: HashSet<FeatureValue> = HashSet::new();
624 if cli_features.all_features {
625 to_add.extend(feature_map.keys().map(|feat| FeatureValue::Feature(*feat)));
626 }
627
628 if cli_features.uses_default_features {
629 to_add.insert(FeatureValue::Feature(INTERNED_DEFAULT));
630 }
631 to_add.extend(cli_features.features.iter().cloned());
632
633 for fv in to_add {
635 match fv {
636 FeatureValue::Feature(feature) => {
637 let feature_edge = Edge {
638 kind: EdgeKind::Feature,
639 node: package_index,
640 public: true,
641 };
642 let index = add_feature(graph, feature, None, feature_edge).1;
643 graph.cli_features.insert(index);
644 }
645 FeatureValue::Dep { .. } => panic!("unexpected cli dep feature {}", fv),
647 FeatureValue::DepFeature {
648 dep_name,
649 dep_feature,
650 weak,
651 } => {
652 let dep_connections = match graph.dep_name_map[&package_index].get(&dep_name) {
653 Some(dep_connections) => dep_connections.clone(),
655 None => {
656 if weak {
659 continue;
660 }
661 panic!(
662 "missing dep graph connection for CLI feature `{}` for member {:?}\n\
663 Please file a bug report at https://github.com/rust-lang/cargo/issues",
664 fv,
665 graph.nodes.get(package_index.index)
666 );
667 }
668 };
669 for (dep_index, is_optional) in dep_connections {
670 if is_optional {
671 let feature_edge = Edge {
673 kind: EdgeKind::Feature,
674 node: package_index,
675 public: true,
676 };
677 let index = add_feature(graph, dep_name, None, feature_edge).1;
678 graph.cli_features.insert(index);
679 }
680 let dep_edge = Edge {
681 kind: EdgeKind::Feature,
682 node: dep_index,
683 public: true,
684 };
685 let index = add_feature(graph, dep_feature, None, dep_edge).1;
686 graph.cli_features.insert(index);
687 }
688 }
689 }
690 }
691}
692
693fn add_internal_features(graph: &mut Graph<'_>, resolve: &Resolve) {
696 let feature_nodes: Vec<(PackageId, NodeId, NodeId, InternedString)> = graph
698 .nodes
699 .iter()
700 .enumerate()
701 .filter_map(|(i, node)| match node {
702 Node::Package { .. } => None,
703 Node::Feature { node_index, name } => {
704 let package_id = graph.package_id_for_index(*node_index);
705 Some((package_id, *node_index, NodeId::new(i, *name), *name))
706 }
707 })
708 .collect();
709
710 for (package_id, package_index, feature_index, feature_name) in feature_nodes {
711 add_feature_rec(
712 graph,
713 resolve,
714 feature_name,
715 package_id,
716 feature_index,
717 package_index,
718 );
719 }
720}
721
722fn add_feature_rec(
727 graph: &mut Graph<'_>,
728 resolve: &Resolve,
729 feature_name: InternedString,
730 package_id: PackageId,
731 from: NodeId,
732 package_index: NodeId,
733) {
734 let feature_map = resolve.summary(package_id).features();
735 let Some(fvs) = feature_map.get(&feature_name) else {
736 return;
737 };
738 for fv in fvs {
739 match fv {
740 FeatureValue::Feature(dep_name) => {
741 let feature_edge = Edge {
742 kind: EdgeKind::Feature,
743 node: package_index,
744 public: true,
745 };
746 let (missing, feat_index) = add_feature(graph, *dep_name, Some(from), feature_edge);
747 if missing {
749 add_feature_rec(
750 graph,
751 resolve,
752 *dep_name,
753 package_id,
754 feat_index,
755 package_index,
756 );
757 }
758 }
759 FeatureValue::Dep { .. } => {}
764 FeatureValue::DepFeature {
765 dep_name,
766 dep_feature,
767 weak,
773 } => {
774 let dep_indexes = match graph.dep_name_map[&package_index].get(dep_name) {
775 Some(indexes) => indexes.clone(),
776 None => {
777 tracing::debug!(
778 "enabling feature {} on {}, found {}/{}, \
779 dep appears to not be enabled",
780 feature_name,
781 package_id,
782 dep_name,
783 dep_feature
784 );
785 continue;
786 }
787 };
788 for (dep_index, is_optional) in dep_indexes {
789 let dep_pkg_id = graph.package_id_for_index(dep_index);
790 if is_optional && !weak {
791 let feature_edge = Edge {
793 kind: EdgeKind::Feature,
794 node: package_index,
795 public: true,
796 };
797 add_feature(graph, *dep_name, Some(from), feature_edge);
798 }
799 let dep_edge = Edge {
800 kind: EdgeKind::Feature,
801 node: dep_index,
802 public: true,
803 };
804 let (missing, feat_index) =
805 add_feature(graph, *dep_feature, Some(from), dep_edge);
806 if missing {
807 add_feature_rec(
808 graph,
809 resolve,
810 *dep_feature,
811 dep_pkg_id,
812 feat_index,
813 dep_index,
814 );
815 }
816 }
817 }
818 }
819 }
820}