You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: unit_dependencies.rs
    path of file: ./repos/cargo/src/cargo/core/compiler
    
    the code of the file until where you have to start completion: //! Constructs the dependency graph for compilation.
//!
//! Rust code is typically organized as a set of Cargo packages. The
//! dependencies between the packages themselves are stored in the
//! [`Resolve`] struct. However, we can't use that information as is for
//! compilation! A package typically contains several targets, or crates,
//! and these targets has inter-dependencies. For example, you need to
//! compile the `lib` target before the `bin` one, and you need to compile
//! `build.rs` before either of those.
//!
//! So, we need to lower the `Resolve`, which specifies dependencies between
//! *packages*, to a graph of dependencies between their *targets*, and this
//! is exactly what this module is doing! Well, almost exactly: another
//! complication is that we might want to compile the same target several times
//! (for example, with and without tests), so we actually build a dependency
//! graph of [`Unit`]s, which capture these properties.

use std::collections::{HashMap, HashSet};

use tracing::trace;

use crate::core::compiler::artifact::match_artifacts_kind_with_targets;
use crate::core::compiler::unit_graph::{UnitDep, UnitGraph};
use crate::core::compiler::{
    CompileKind, CompileMode, CrateType, RustcTargetData, Unit, UnitInterner,
};
use crate::core::dependency::{Artifact, ArtifactTarget, DepKind};
use crate::core::profiles::{Profile, Profiles, UnitFor};
use crate::core::resolver::features::{FeaturesFor, ResolvedFeatures};
use crate::core::resolver::Resolve;
use crate::core::{Dependency, Package, PackageId, PackageSet, Target, TargetKind, Workspace};
use crate::ops::resolve_all_features;
use crate::util::interning::InternedString;
use crate::util::GlobalContext;
use crate::CargoResult;

const IS_NO_ARTIFACT_DEP: Option<&'static Artifact> = None;

/// Collection of stuff used while creating the [`UnitGraph`].
struct State<'a, 'gctx> {
    ws: &'a Workspace<'gctx>,
    gctx: &'gctx GlobalContext,
    /// Stores the result of building the [`UnitGraph`].
    unit_dependencies: UnitGraph,
    package_set: &'a PackageSet<'gctx>,
    usr_resolve: &'a Resolve,
    usr_features: &'a ResolvedFeatures,
    /// Like `usr_resolve` but for building standard library (`-Zbuild-std`).
    std_resolve: Option<&'a Resolve>,
    /// Like `usr_features` but for building standard library (`-Zbuild-std`).
    std_features: Option<&'a ResolvedFeatures>,
    /// `true` while generating the dependencies for the standard library.
    is_std: bool,
    /// The mode we are compiling in. Used for preventing from building lib thrice.
    global_mode: CompileMode,
    target_data: &'a RustcTargetData<'gctx>,
    profiles: &'a Profiles,
    interner: &'a UnitInterner,
    // Units for `-Zrustdoc-scrape-examples`.
    scrape_units: &'a [Unit],

    /// A set of edges in `unit_dependencies` where (a, b) means that the
    /// dependency from a to b was added purely because it was a dev-dependency.
    /// This is used during `connect_run_custom_build_deps`.
    dev_dependency_edges: HashSet<(Unit, Unit)>,
}

/// A boolean-like to indicate if a `Unit` is an artifact or not.
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum IsArtifact {
    Yes,
    No,
}

impl IsArtifact {
    pub fn is_true(&self) -> bool {
        matches!(self, IsArtifact::Yes)
    }
}

/// Then entry point for building a dependency graph of compilation units.
///
/// You can find some information for arguments from doc of [`State`].
#[tracing::instrument(skip_all)]
pub fn build_unit_dependencies<'a, 'gctx>(
    ws: &'a Workspace<'gctx>,
    package_set: &'a PackageSet<'gctx>,
    resolve: &'a Resolve,
    features: &'a ResolvedFeatures,
    std_resolve: Option<&'a (Resolve, ResolvedFeatures)>,
    roots: &[Unit],
    scrape_units: &[Unit],
    std_roots: &HashMap<CompileKind, Vec<Unit>>,
    global_mode: CompileMode,
    target_data: &'a RustcTargetData<'gctx>,
    profiles: &'a Profiles,
    interner: &'a UnitInterner,
) -> CargoResult<UnitGraph> {
    if roots.is_empty() {
        // If -Zbuild-std, don't attach units if there is nothing to build.
        // Otherwise, other parts of the code may be confused by seeing units
        // in the dep graph without a root.
        return Ok(HashMap::new());
    }
    let (std_resolve, std_features) = match std_resolve {
        Some((r, f)) =
    
fn connect_run_custom_build_deps(state: &mut State<'_, '_>) {
    let mut new_deps = Vec::new();

    {
        let state = &*state;
        // First up build a reverse dependency map. This is a mapping of all
        // `RunCustomBuild` known steps to the unit which depends on them. For
        // example a library might depend on a build script, so this map will
        // have the build script as the key and the library would be in the
        // value's set.
        let mut reverse_deps_map = HashMap::new();
        for (unit, deps) in state.unit_dependencies.iter() {
            for dep in deps {
                if dep.unit.mode == CompileMode::RunCustomBuild {
                    reverse_deps_map
                        .entry(dep.unit.clone())
                        .or_insert_with(HashSet::new)
                        .insert(unit);
                }
            }
        }

        // Next, we take a look at all build scripts executions listed in the
        // dependency map. Our job here is to take everything that depends on
        // this build script (from our reverse map above) and look at the other
        // package dependencies of these parents.
        //
        // If we depend on a linkable target and the build script mentions
        // `links`, then we depend on that package's build script! Here we use
        // `dep_build_script` to manufacture an appropriate build script unit to
        // depend on.
        for unit in state
            .unit_dependencies
            .keys()
            .filter(|k| k.mode == CompileMode::RunCustomBuild)
        {
            // This list of dependencies all depend on `unit`, an execution of
            // the build script.
            let Some(reverse_deps) = reverse_deps_map.get(unit) else {
                continue;
            };

            let to_add = reverse_deps
                .iter()
                // Get all sibling dependencies of `unit`
                .flat_map(|reverse_dep| {
                    state.unit_dependencies[reverse_dep]
                        .iter()
                        .map(move |a| (reverse_dep, a))
                })
                // Only deps with `links`.
                .filter(|(_parent, other)| {
                    other.unit.pkg != unit.pkg
                        && other.unit.target.is_linkable()
                        && other.unit.pkg.manifest().links().is_some()
                })
                // Avoid cycles when using the doc --scrape-examples feature:
                // Say a workspace has crates A and B where A has a build-dependency on B.
                // The Doc units for A and B will have a dependency on the Docscrape for both A and B.
                // So this would add a dependency from B-build to A-build, causing a cycle:
                //   B (build) -> A (build) -> B(build)
                // See the test scrape_examples_avoid_build_script_cycle for a concrete example.
                // To avoid this cycle, we filter out the B -> A (docscrape) dependency.
                .filter(|(_parent, other)| !other.unit.mode.is_doc_scrape())
                // Skip dependencies induced via dev-dependencies since
                // connections between `links` and build scripts only happens
                // via normal dependencies. Otherwise since dev-dependencies can
                // be cyclic we could have cyclic build-script executions.
                .filter_map(move |(parent, other)| {
                    if state
                        .dev_dependency_edges
                        .contains(&((*parent).clone(), other.unit.clone()))
                    {
                        None
                    } else {
                        Some(other)
                    }
                })
                // Get the RunCustomBuild for other lib.
                .filter_map(|other| {
                    state.unit_dependencies[&other.unit]
                        .iter()
                        .find(|other_dep| other_dep.unit.mode == CompileMode::RunCustomBuild)
                        .cloned()
                })
                .collect::<HashSet<_>>();

            if !to_add.is_empty() {
                // (RunCustomBuild, set(other RunCustomBuild))
                new_deps.push((unit.clone(), to_add));
            }
        }
    }

    // And finally, add in all the missing dependencies!
    for (unit, new_deps) in new_deps {
        state
            .unit_dependencies
            .get_mut(&unit)
            .unwrap()
            .extend(new_deps);
    }
}