Remove dependency on `guppy`

finchie
May 9, 2024, 6:32 AM
VMWXIDPEMIGIVB4YP4YKM2GFIO6O6J7HEYS5FNYPTUSQ3X5MWTMAC

Dependencies

  • [2] 3NPBHM5F Support cargo's unstable `unit-graph` feature
  • [3] 7CVIL7UJ Create simple metadata parser
  • [4] T34OV3YQ Store timings output in `timings::Output` struct
  • [5] PJPTNU2S Skip re-generating `--timings=json` on every run
  • [6] XVQXXAGZ Add support for generating treemaps
  • [7] BRXHJFU7 Refactor measurements into `annotations` module
  • [8] ZPFD3275 Switch from `cargo_metadata`+`petgraph` to `guppy`
  • [9] C43IWI7G Move visualization logic into separate module
  • [10] YA5ITLOV Add support for Sankey diagrams
  • [11] WFBF7VS6 Split `annotations` and `graph` into 2 separate modules
  • [12] UXJFRBBL Move graph functionality into `graph` module
  • [13] Q3Z6XMP5 Migrate dependency tree to `petgraph::Graph`
  • [14] UKNTVY7Z Add treemap visualization code
  • [15] B2L26LOA Store index of dependency nodes
  • [16] UQJO24KB Use `forceatlas2` to construct graph layout
  • [17] OPTMCUTB Use timings `duration` to set size of rendered node
  • [18] ZEN3WUPD Add support for histogram charts
  • [19] LOR3KOXG Parse JSON output from `cargo build --timings`
  • [20] 475UXTLY Use multiple force-directed layout algorithms to improve graph readability
  • [21] JVYWRCPT Add basic chart visualisation
  • [22] V2NPEIA6 Use custom types to deserialize `--timings=json` output
  • [23] L6QJNN62 Parse rustc self-profile data using `analyzeme`

Change contents

  • replacement in src/visualize/treemap.rs at line 1
    [3.35][3.0:28]()
    use crate::AnnotationGraph;
    [3.35]
    [3.60]
    use crate::graph::Node;
    use crate::{AnnotationGraph, Measurement};
  • replacement in src/visualize/treemap.rs at line 8
    [3.154][3.154:189]()
    use guppy::graph::PackageMetadata;
    [3.154]
    [3.189]
    use petgraph::Direction;
  • replacement in src/visualize/treemap.rs at line 24
    [3.505][3.29:64](),[3.64][3.536:578](),[3.536][3.536:578]()
    annotations: &AnnotationGraph,
    packages: &[PackageMetadata<'graph>],
    [3.505]
    [3.578]
    annotations: &'graph AnnotationGraph,
    packages: Vec<&'graph Node>,
  • edit in src/visualize/treemap.rs at line 28
    [3.642][3.642:835]()
    for pkg in packages {
    // Recursively call this function for all direct dependencies
    let direct_dependencies = pkg.direct_links().map(|link| link.to()).collect::<Vec<_>>();
  • replacement in src/visualize/treemap.rs at line 29
    [3.836][3.836:1415]()
    let empty_vec = Vec::new();
    let self_times = annotations
    .pkg(pkg.id())
    .map(|node| node.timings().unwrap_or(&empty_vec))
    .unwrap_or(&empty_vec)
    .iter()
    .map(|message| TreemapData {
    value: message.duration,
    id: None,
    name: Some(format!("{:?} {:?}", message.mode, message.target.kind)),
    upper_label: None,
    visual_dimension: None,
    children: vec![],
    children_visible_min: None,
    });
    [3.836]
    [3.1415]
    for node in packages {
    let self_times = node.timings().iter().map(|message| TreemapData {
    value: message.duration,
    id: None,
    name: Some(format!("{:?} {:?}", message.mode, message.target.kind)),
    upper_label: None,
    visual_dimension: None,
    children: vec![],
    children_visible_min: None,
    });
  • replacement in src/visualize/treemap.rs at line 40
    [3.1416][3.1416:1484]()
    let mut children = data(annotations, &direct_dependencies);
    [3.1416]
    [3.1484]
    // Recursively call this function for all direct dependencies
    let direct_dependencies = annotations
    .node_edges(node, Direction::Outgoing)
    .collect::<Vec<_>>();
    let mut children = data(annotations, direct_dependencies);
  • edit in src/visualize/treemap.rs at line 46
    [3.1521][3.1521:1882]()
    let mut total_duration = 0_f64;
    for child in &children {
    total_duration += child.value;
    }
    let dependent_count = pkg.reverse_direct_links().count();
    let relative_duration = if dependent_count == 0 {
    total_duration
    } else {
    total_duration / (dependent_count as f64)
    };
  • replacement in src/visualize/treemap.rs at line 48
    [3.1924][3.1924:1962]()
    value: relative_duration,
    [3.1924]
    [3.1962]
    value: annotations.variable(
    node,
    crate::Variable::TotalDuration,
    Measurement::Relative,
    ),
  • replacement in src/visualize/treemap.rs at line 54
    [3.1984][3.1984:2032]()
    name: Some(pkg.name().to_string()),
    [3.1984]
    [3.2032]
    name: Some(node.name().to_string()),
  • replacement in src/visualize/sankey.rs at line 4
    [3.200][3.127:242](),[3.127][3.127:242]()
    annotations
    .packages()
    .map(|id| annotations.metadata(id).unwrap().name())
    .collect()
    [3.200]
    [3.215]
    annotations.packages().map(|node| node.name()).collect()
  • replacement in src/visualize/sankey.rs at line 8
    [3.302][3.340:457](),[3.340][3.340:457]()
    let links = annotations.links().collect::<Vec<_>>();
    let mut sankey_links = Vec::with_capacity(links.len());
    [3.302]
    [3.450]
    let mut sankey_links = Vec::new();
  • replacement in src/visualize/sankey.rs at line 10
    [3.451][3.458:630]()
    for (from, to) in links {
    let edge_weight = annotations
    .variable(to, Variable::UnitDuration, Measurement::Relative)
    .unwrap_or(0_f64);
    [3.451]
    [3.1157]
    for (source, target) in annotations.edges() {
    let edge_weight =
    annotations.variable(target, Variable::UnitDuration, Measurement::Relative);
  • replacement in src/visualize/sankey.rs at line 14
    [3.1158][3.631:851]()
    let (from_meta, to_meta) = (
    annotations.metadata(from).unwrap(),
    annotations.metadata(to).unwrap(),
    );
    sankey_links.push((from_meta.name(), to_meta.name(), edge_weight));
    [3.1158]
    [3.1217]
    sankey_links.push((source.name(), target.name(), edge_weight));
  • edit in src/visualize/mod.rs at line 44
    [3.188]
    [3.188]
    let data = treemap::data(annotations, annotations.roots().collect::<Vec<_>>());
  • replacement in src/visualize/mod.rs at line 46
    [3.215][3.1131:1211]()
    .data(treemap::data(annotations, &annotations.root_packages()))
    [3.215]
    [3.268]
    .data(data)
  • replacement in src/visualize/mod.rs at line 52
    [3.565][3.1212:1282]()
    .levels(treemap::levels(annotations.links().count()))
    [3.565]
    [3.635]
    .levels(treemap::levels(annotations.edges().count()))
  • replacement in src/visualize/histogram.rs at line 29
    [3.1528][3.1528:1623]()
    .filter_map(|id| annotations.variable(id, Variable::UnitDuration, Measurement::Exact))
    [3.1528]
    [3.1623]
    .map(|id| annotations.variable(id, Variable::UnitDuration, Measurement::Exact))
  • replacement in src/visualize/histogram.rs at line 52
    [3.1790][3.1790:1885]()
    .filter_map(|id| annotations.variable(id, Variable::UnitDuration, Measurement::Exact))
    [3.1790]
    [3.1885]
    .map(|id| annotations.variable(id, Variable::UnitDuration, Measurement::Exact))
  • edit in src/visualize/graph.rs at line 1
    [3.146]
    [3.555]
    use crate::graph::Node;
  • edit in src/visualize/graph.rs at line 5
    [3.204][3.1966:2012]()
    use guppy::PackageId;
    use indexmap::IndexMap;
  • replacement in src/visualize/graph.rs at line 8
    [3.421][3.352:428](),[3.651][3.352:428](),[3.2051][3.352:428](),[3.352][3.352:428](),[3.428][3.2052:2134](),[3.2134][3.540:561](),[3.540][3.540:561](),[3.561][3.2135:2176](),[3.2176][3.601:622](),[3.601][3.601:622]()
    ) -> impl Iterator<Item = (&'graph PackageId, forceatlas2::Node<f64, 2>)> {
    let link_index: IndexMap<&PackageId, usize> = annotations
    .packages()
    .enumerate()
    .map(|(index, id)| (*id, index))
    .collect();
    [3.651]
    [3.2177]
    ) -> impl Iterator<Item = (&'graph Node<'graph>, forceatlas2::Node<f64, 2>)> {
  • replacement in src/visualize/graph.rs at line 10
    [3.2205][3.2205:2292](),[3.2292][3.821:879](),[3.821][3.821:879]()
    .links()
    .map(|(from, to)| (link_index.get(from), link_index.get(to)))
    .map(|(from, to)| (*from.unwrap(), *to.unwrap()))
    [3.2205]
    [3.879]
    .edges()
    // Get the graph index of both nodes connected to the edge (NodeIndex)
    .map(|(source, target)| (source.index(), target.index()))
    // Get the integer representation of that index (usize)
    .map(|(source, target)| (source.index(), target.index()))
  • replacement in src/visualize/graph.rs at line 17
    [3.932][3.2293:2458]()
    let sizes = link_index.keys().map(|id| {
    annotations
    .variable(id, Variable::UnitDuration, Measurement::Exact)
    .unwrap_or(0_f64)
    [3.932]
    [3.2458]
    let sizes = annotations.edges().map(|(source, _target)| {
    annotations.variable(source, Variable::UnitDuration, Measurement::Exact)
  • replacement in src/visualize/graph.rs at line 27
    [3.1214][3.1214:1215](),[3.1395][3.1395:1442](),[3.1442][3.2467:2543]()
    layout
    .nodes
    .into_iter()
    .zip(annotations.packages())
    .map(|(node, id)| (*id, node))
    [3.1214]
    [3.1548]
    annotations.packages().zip(layout.nodes.into_iter())
  • replacement in src/visualize/graph.rs at line 37
    [3.1831][3.357:385](),[3.385][3.2656:2805]()
    .map(|(id, node)| {
    let unit_time = annotations
    .variable(id, Variable::UnitDuration, Measurement::Exact)
    .unwrap_or(0_f64);
    [3.1831]
    [3.708]
    .map(|(graph_node, layout_node)| {
    let unit_time =
    annotations.variable(graph_node, Variable::UnitDuration, Measurement::Exact);
  • replacement in src/visualize/graph.rs at line 43
    [3.832][3.832:875](),[3.875][3.2806:2882](),[3.2882][3.945:1011](),[3.945][3.945:1011]()
    id: id.repr().to_string(),
    name: annotations.metadata(id).unwrap().name().to_string(),
    x: node.pos.x(),
    y: node.pos.y(),
    [3.832]
    [3.1011]
    id: graph_node.id().repr.clone(),
    name: graph_node.name().to_string(),
    x: layout_node.pos.x(),
    y: layout_node.pos.y(),
  • replacement in src/visualize/graph.rs at line 56
    [3.2911][3.2911:2928]()
    .links()
    [3.2911]
    [3.2376]
    .edges()
  • replacement in src/visualize/graph.rs at line 58
    [3.2438][3.2929:3023]()
    source: source.repr().to_string(),
    target: target.repr().to_string(),
    [3.2438]
    [3.2542]
    source: source.id().repr.to_string(),
    target: target.id().repr.to_string(),
  • edit in src/main.rs at line 2
    [3.24][3.24:25](),[3.25][3.0:51](),[3.63][3.0:51](),[3.85][3.0:51]()
    use guppy::{graph::PackageGraph, MetadataCommand};
  • edit in src/main.rs at line 7
    [3.1078]
    [3.741]
    use cargo_metadata::MetadataCommand;
  • replacement in src/main.rs at line 20
    [3.2758][3.2758:2889]()
    let mut metadata_cmd = MetadataCommand::new();
    let package_graph = PackageGraph::from_command(&mut metadata_cmd).unwrap();
    [3.2758]
    [3.896]
    let metadata = MetadataCommand::new().exec().unwrap();
  • replacement in src/main.rs at line 22
    [3.897][2.372:461]()
    let graph = AnnotationGraph::new(&package_graph, timings, self_profile, unit_graph);
    [3.897]
    [3.3253]
    let graph = AnnotationGraph::new(metadata, timings, self_profile, &unit_graph);
  • replacement in src/graph/mod.rs at line 3
    [3.3482][3.3482:3600]()
    use guppy::graph::{DependencyDirection, PackageGraph, PackageMetadata};
    use guppy::PackageId;
    use indexmap::IndexMap;
    [3.3482]
    [3.3600]
    use cargo_metadata::{Metadata, Package, PackageId};
  • edit in src/graph/mod.rs at line 7
    [3.3711]
    [3.3711]
    use petgraph::visit::EdgeRef;
  • edit in src/graph/mod.rs at line 22
    [3.3935]
    [3.3935]
    /// A node in the unit graph
  • replacement in src/graph/mod.rs at line 25
    [3.3985][3.3985:4056]()
    id: &'graph PackageId,
    timings: Option<Vec<timings::Message>>,
    [3.3985]
    [3.4056]
    index: usize,
    metadata: Package,
    unit: &'graph unit_graph::Unit,
    timings: Vec<timings::Message>,
  • replacement in src/graph/mod.rs at line 32
    [3.4087][3.4087:4179]()
    pub fn timings(&self) -> Option<&Vec<timings::Message>> {
    self.timings.as_ref()
    [3.4087]
    [3.4179]
    pub fn index(&self) -> NodeIndex {
    NodeIndex::new(self.index)
    }
    pub fn id(&self) -> &PackageId {
    &self.unit.pkg_id
    }
    pub fn name(&self) -> &str {
    self.metadata.name.as_str()
    }
    pub fn timings(&self) -> &Vec<timings::Message> {
    &self.timings
  • replacement in src/graph/mod.rs at line 49
    [3.4188][3.4188:4212]()
    #[derive(Debug, Clone)]
    [3.4188]
    [3.1103]
    #[derive(Debug)]
  • edit in src/graph/mod.rs at line 51
    [3.1140][3.4245:4286](),[3.4245][3.4245:4286]()
    package_graph: &'graph PackageGraph,
  • replacement in src/graph/mod.rs at line 52
    [3.4322][3.4322:4376]()
    node_indices: IndexMap<&'graph PackageId, usize>,
    [3.4322]
    [3.4376]
    timings: timings::Output,
    self_profile: self_profile::ProfileCollection,
    unit_graph: &'graph unit_graph::UnitGraph,
  • replacement in src/graph/mod.rs at line 59
    [3.4430][3.4430:4475]()
    package_graph: &'graph PackageGraph,
    [3.4430]
    [3.1181]
    metadata: Metadata,
  • replacement in src/graph/mod.rs at line 62
    [3.1274][2.524:567]()
    unit_graph: unit_graph::UnitGraph,
    [3.1274]
    [3.4539]
    unit_graph: &'graph unit_graph::UnitGraph,
  • replacement in src/graph/mod.rs at line 64
    [3.4555][2.568:600]()
    dbg!(unit_graph.roots);
    [3.4555]
    [3.1275]
    dbg!(&unit_graph.roots);
  • replacement in src/graph/mod.rs at line 67
    [3.8252][3.4555:4623](),[3.4555][3.4555:4623]()
    let node_indices = package_graph
    .package_ids()
    [3.8252]
    [3.4623]
    let nodes = unit_graph
    .units
    .iter()
  • replacement in src/graph/mod.rs at line 71
    [3.4648][3.4648:4926](),[3.4926][3.1344:1394](),[3.1394][3.4971:5340](),[3.4971][3.4971:5340]()
    .map(|(index, id)| (id, index))
    .collect::<IndexMap<&PackageId, usize>>();
    // Iterate over node_indicies.keys() to preserve ordering
    let nodes = node_indices.keys().map(|id| Element::Node {
    weight: Node {
    id,
    timings: timings.repr.remove(id),
    },
    });
    let package_set = package_graph.resolve_all();
    let edges = package_set
    .links(DependencyDirection::Forward)
    .map(|link| Element::Edge {
    source: *node_indices.get(link.from().id()).unwrap(),
    target: *node_indices.get(link.to().id()).unwrap(),
    weight: (),
    [3.4648]
    [3.5340]
    .map(|(index, unit)| Element::Node {
    weight: Node {
    index,
    metadata: metadata[&unit.pkg_id].clone(),
    unit,
    timings: timings.repr.remove(&unit.pkg_id).unwrap(),
    },
  • edit in src/graph/mod.rs at line 79
    [3.5356]
    [3.5356]
    let edges = unit_graph
    .units
    .iter()
    .map(|unit| unit.dependencies.iter())
    .enumerate()
    .map(|(index, deps)| {
    deps.map(move |dep| Element::Edge {
    source: index,
    target: dep.index,
    weight: (),
    })
    })
    .flatten();
  • edit in src/graph/mod.rs at line 96
    [3.5435][3.5435:5462]()
    package_graph,
  • replacement in src/graph/mod.rs at line 97
    [3.5481][3.5481:5507]()
    node_indices,
    [3.5481]
    [3.5507]
    timings,
    self_profile,
    unit_graph,
  • edit in src/graph/mod.rs at line 101
    [3.5517][3.5517:5726]()
    }
    pub fn root_packages(&self) -> Vec<PackageMetadata> {
    self.package_graph
    .resolve_all()
    .root_packages(DependencyDirection::Forward)
    .collect::<Vec<_>>()
  • replacement in src/graph/mod.rs at line 103
    [3.5733][3.5733:5892]()
    fn node_index(&self, id: &PackageId) -> Option<NodeIndex> {
    let node_index = *self.node_indices.get(id)?;
    Some(NodeIndex::new(node_index))
    [3.5733]
    [3.5892]
    pub fn roots(&'graph self) -> impl Iterator<Item = &'graph Node> {
    self.unit_graph
    .roots
    .iter()
    .map(|root| NodeIndex::new(*root))
    .map(|index| &self.graph[index])
  • replacement in src/graph/mod.rs at line 111
    [3.5899][3.5899:6041]()
    pub fn pkg(&self, id: &PackageId) -> Option<&Node> {
    let node_index = self.node_index(id)?;
    Some(&self.graph[node_index])
    [3.5899]
    [3.6041]
    pub fn packages(&'graph self) -> impl Iterator<Item = &'graph Node> {
    self.graph.node_indices().map(|index| &self.graph[index])
  • replacement in src/graph/mod.rs at line 115
    [3.6048][3.6048:6147]()
    pub fn packages(&self) -> impl Iterator<Item = &&PackageId> {
    self.node_indices.keys()
    [3.6048]
    [3.6147]
    pub fn edges(&'graph self) -> impl Iterator<Item = (&'graph Node, &'graph Node)> {
    self.graph
    .edge_indices()
    .map(|edge| self.graph.edge_endpoints(edge))
    .map(Option::unwrap)
    .map(|(source, target)| (&self.graph[source], &self.graph[target]))
  • replacement in src/graph/mod.rs at line 123
    [3.6154][3.6154:6230]()
    pub fn links(&self) -> impl Iterator<Item = (&PackageId, &PackageId)> {
    [3.6154]
    [3.6230]
    pub fn node_edges(
    &'graph self,
    node: &Node,
    direction: Direction,
    ) -> impl Iterator<Item = &'graph Node> {
    let node_index = node.index();
  • replacement in src/graph/mod.rs at line 130
    [3.6249][3.6249:6380]()
    .raw_edges()
    .iter()
    .map(|edge| (self.graph[edge.source()].id, self.graph[edge.target()].id))
    [3.6249]
    [3.6380]
    .edges_directed(node_index, direction)
    .map(move |edge| match direction {
    Direction::Outgoing => edge.target(),
    Direction::Incoming => edge.source(),
    })
    .map(|index| &self.graph[index])
  • replacement in src/graph/mod.rs at line 138
    [3.6387][3.6387:6941]()
    pub fn metadata(&self, id: &PackageId) -> Result<PackageMetadata, guppy::Error> {
    self.package_graph.metadata(id)
    }
    pub fn dependents(&self, id: &PackageId) -> Option<usize> {
    let node_index = self.node_index(id)?;
    let dependents = self
    .graph
    .edges_directed(node_index, Direction::Incoming)
    .count();
    Some(dependents)
    }
    pub fn variable(
    &self,
    id: &PackageId,
    variable: Variable,
    measurement: Measurement,
    ) -> Option<f64> {
    [3.6387]
    [3.6941]
    pub fn variable(&self, node: &Node, variable: Variable, measurement: Measurement) -> f64 {
  • replacement in src/graph/mod.rs at line 141
    [3.7030][3.7030:7126]()
    let node = self.pkg(id)?;
    let timings = node.timings.as_ref()?;
    [3.7030]
    [3.7126]
    let timings = &node.timings;
  • edit in src/graph/mod.rs at line 144
    [3.7199][3.7199:7307]()
    if id.repr().contains("windows") {
    dbg!(id, timings);
    }
  • edit in src/graph/mod.rs at line 147
    [3.7394][3.7394:7449]()
    let node_index = self.node_index(id)?;
  • replacement in src/graph/mod.rs at line 149
    [3.7516][3.7516:7590]()
    .neighbors_directed(node_index, Direction::Outgoing);
    [3.7516]
    [3.7590]
    .neighbors_directed(node.index(), Direction::Outgoing);
  • replacement in src/graph/mod.rs at line 152
    [3.7634][3.7634:7706]()
    .filter_map(|dep| self.graph[dep].timings.as_ref())
    [3.7634]
    [3.7706]
    .map(|dep| &self.graph[dep].timings)
  • replacement in src/graph/mod.rs at line 156
    [3.7784][3.7784:7934]()
    let self_timings = self
    .variable(id, Variable::UnitDuration, measurement)
    .unwrap_or(0_f64);
    [3.7784]
    [3.7934]
    let self_timings = self.variable(node, Variable::UnitDuration, measurement);
  • replacement in src/graph/mod.rs at line 161
    [3.8012][3.8012:8045]()
    Some(match measurement {
    [3.8012]
    [3.8045]
    match measurement {
  • replacement in src/graph/mod.rs at line 164
    [3.8137][3.8137:8199]()
    let dependents = self.dependents(id)? as f64;
    [3.8137]
    [3.8199]
    let dependents = self
    .graph
    .edges_directed(node.index(), Direction::Incoming)
    .count() as f64;
  • replacement in src/graph/mod.rs at line 175
    [3.8388][3.8388:8399]()
    })
    [3.8388]
    [3.8399]
    }
  • replacement in src/annotations/timings.rs at line 5
    [3.61][3.61:83]()
    use guppy::PackageId;
    [3.108]
    [3.149]
    use cargo_metadata::PackageId;
  • replacement in src/annotations/timings.rs at line 34
    [3.1627][3.968:1015]()
    pub package_id: cargo_metadata::PackageId,
    [3.1627]
    [3.1395]
    pub package_id: PackageId,
  • edit in src/annotations/timings.rs at line 41
    [3.907]
    [3.146]
    #[derive(Clone, Debug)]
  • replacement in src/annotations/timings.rs at line 100
    [3.1964][3.1964:2128]()
    let pkg_id = PackageId::new(json_message.package_id.repr.clone());
    let pkg_timings: &mut Vec<Message> = timings.entry(pkg_id).or_default();
    [3.1964]
    [3.2128]
    let pkg_timings: &mut Vec<Message> =
    timings.entry(json_message.package_id.clone()).or_default();
  • edit in Cargo.toml at line 12
    [3.1769][3.1337:1354](),[3.1656][3.1337:1354](),[3.1354][3.8408:8427]()
    guppy = "0.17.5"
    indexmap = "2.2.6"
  • edit in Cargo.lock at line 6
    [3.1670][3.1355:1619](),[3.1619][3.8334:8349]()
    name = "ahash"
    version = "0.8.11"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
    dependencies = [
    "cfg-if",
    "getrandom",
    "once_cell",
    "version_check",
    "zerocopy",
    ]
    [[package]]
  • edit in Cargo.lock at line 99
    [3.1963][3.1635:1879]()
    name = "cfg-expr"
    version = "0.15.8"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02"
    dependencies = [
    "smallvec",
    "target-lexicon",
    ]
    [[package]]
  • edit in Cargo.lock at line 156
    [3.2790][3.1880:2076]()
    [[package]]
    name = "debug-ignore"
    version = "1.0.5"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "ffe7ed1d93f4553003e20b629abe9085e1e81b1429520f897f8f8860bc6dfc21"
  • edit in Cargo.lock at line 190
    [3.3063][3.2077:2087](),[3.2817][3.2077:2087](),[3.2087][3.8447:8460]()
    "guppy",
    "indexmap",
  • edit in Cargo.lock at line 255
    [3.2520][3.2520:3003]()
    ]
    [[package]]
    name = "guppy"
    version = "0.17.5"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "34e99a7734579b834a076ef11789783c153c6eb5fb3520ed15bc41f483f0f317"
    dependencies = [
    "ahash",
    "camino",
    "cargo_metadata",
    "cfg-if",
    "debug-ignore",
    "fixedbitset",
    "guppy-workspace-hack",
    "indexmap",
    "itertools",
    "nested",
    "once_cell",
    "pathdiff",
    "petgraph",
    "semver",
    "serde",
    "serde_json",
    "smallvec",
    "static_assertions",
    "target-spec",
  • edit in Cargo.lock at line 256
    [3.3005][3.3005:3209]()
    [[package]]
    name = "guppy-workspace-hack"
    version = "0.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "92620684d99f750bae383ecb3be3748142d6095760afd5cbcf2261e9a279d780"
  • edit in Cargo.lock at line 294
    [3.9855][3.2262:2277](),[3.2262][3.2262:2277](),[3.2277][3.3210:3419]()
    ]
    [[package]]
    name = "itertools"
    version = "0.12.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
    dependencies = [
    "either",
  • edit in Cargo.lock at line 379
    [3.2237][3.3435:3625]()
    name = "nested"
    version = "0.1.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "ca2b420f638f07fe83056b55ea190bb815f609ec5a35e7017884a10f78839c9e"
    [[package]]
  • edit in Cargo.lock at line 442
    [3.4348][3.3626:3848](),[3.4358][3.3626:3848]()
    name = "pathdiff"
    version = "0.2.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
    dependencies = [
    "camino",
    ]
    [[package]]
  • edit in Cargo.lock at line 680
    [3.4042][3.4042:4243]()
    [[package]]
    name = "static_assertions"
    version = "1.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
  • edit in Cargo.lock at line 689
    [3.4041][3.4041:4074](),[3.4074][3.4244:4700]()
    "unicode-ident",
    ]
    [[package]]
    name = "target-lexicon"
    version = "0.12.14"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
    [[package]]
    name = "target-spec"
    version = "3.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "36a8e795b1824524d13cdf04f73cf8b4f244ce86c96b4d2a83a6ca1a753d2752"
    dependencies = [
    "cfg-expr",
    "guppy-workspace-hack",
    "target-lexicon",
  • edit in Cargo.lock at line 820
    [3.7980][3.7980:7993](),[3.7993][3.4959:5431](),[3.4959][3.4959:5431]()
    [[package]]
    name = "zerocopy"
    version = "0.7.32"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
    dependencies = [
    "zerocopy-derive",
    ]
    [[package]]
    name = "zerocopy-derive"
    version = "0.7.32"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    ]