Skip to main content

pedant_core/resolution/rust/snapshot/
target.rs

1//! The root-only target snapshot: exactly the sources one Cargo target's
2//! module closure reaches.
3//!
4//! This is the source-discovery contract supply-chain hashing consumes, so it
5//! never admits a dependency package's sources and never returns a partial
6//! closure.
7
8use std::sync::Arc;
9
10use crate::resolution::rust::identity::TargetId;
11use crate::resolution::rust::project::RustProject;
12
13use super::authority;
14use super::closure::{self, ClosureEntry};
15use super::error::RustSnapshotError;
16use super::source::{self, RustSource};
17use super::store::{SourceStore, refuse};
18
19/// Every source one Cargo target reaches, with its exact bytes and IR.
20#[derive(Debug)]
21pub struct RustTargetSnapshot {
22    target: TargetId,
23    crate_root: Arc<str>,
24    sources: Box<[RustSource]>,
25}
26
27impl RustTargetSnapshot {
28    /// The target this snapshot was taken for.
29    pub fn target(&self) -> TargetId {
30        self.target
31    }
32
33    /// The repository-relative entry point the closure started at.
34    pub fn crate_root(&self) -> &str {
35        &self.crate_root
36    }
37
38    /// Every reached source, sorted by repository-relative path.
39    pub fn sources(&self) -> &[RustSource] {
40        &self.sources
41    }
42
43    /// The reached source at one repository-relative path.
44    pub fn source(&self, path: &str) -> Option<&RustSource> {
45        source::find(&self.sources, path)
46    }
47}
48
49/// Validate the target's authority, then walk only its module closure.
50pub(in crate::resolution::rust) fn build(
51    project: &RustProject,
52    id: TargetId,
53) -> Result<RustTargetSnapshot, RustSnapshotError> {
54    let target = authority::validated_target(project, id)?;
55    let mut store = SourceStore::new(project.root(), project.limits());
56    let mut failures = Vec::new();
57    let entry = ClosureEntry {
58        target_name: target.name(),
59        entry_path: target.entry_path(),
60        edition: target.edition(),
61    };
62    let closure = closure::walk_unit(&mut store, &entry, &mut failures);
63    match (closure, failures.is_empty()) {
64        (Some(_), true) => Ok(RustTargetSnapshot {
65            target: id,
66            crate_root: Arc::clone(&target.entry_path),
67            sources: store.finish(),
68        }),
69        (None, _) | (Some(_), false) => Err(refuse(&store, failures)),
70    }
71}