in guppy/src/graph/build.rs [589:652]
fn resolve<'a>(
&'a self,
resolved_name: &str,
package_id: &PackageId,
) -> Result<(&'g str, impl Iterator<Item = &'g Dependency> + 'a), Error> {
// This method needs to reconcile three separate sources of data:
// 1. The metadata for each package, which is basically a parsed version of the Cargo.toml
// for that package.
// 2. The list of dependencies for the source package, which is also extracted from
// Cargo.toml for that package.
// 3. The "resolve" section of the manifest, which has resolved names and package IDs (this
// is what's passed in).
//
// The below algorithm does a pretty job, but there are some edge cases it has trouble
// handling, primarily around malformed Cargo.toml files. For example, this Cargo.toml file
// will result in a metadata JSON (as of Rust 1.37) that will parse incorrectly:
//
// [dependencies]
// lazy_static = "1"
//
// [build-dependencies]
// lazy_static_new = { package = "lazy_static", version = "1", optional = true }
//
// TODO: Add detection for cases like this.
// Lookup the package ID in the package data.
let (_, package_name, version) = self.package_data.get(package_id).ok_or_else(|| {
Error::PackageGraphConstructError(format!(
"{}: no package data found for dependency '{}'",
self.from_id, package_id
))
})?;
// ---
// Both the following checks verify against the version as well to allow situations like
// this to work:
//
// [dependencies]
// lazy_static = "1"
//
// [dev-dependencies]
// lazy_static = "0.2"
//
// This needs to be done against the renamed map as well.
// ---
// Lookup the name in the renamed map. If a hit is found here we're done.
if let Some((name, deps)) = self.renamed_map.get(resolved_name) {
return Ok((*name, deps.matches_for(version)));
}
// Lookup the name in the original map.
let (name, dep_reqs) = self
.original_map
.get_key_value(package_name.as_str())
.ok_or_else(|| {
Error::PackageGraphConstructError(format!(
"{}: no dependency information found for '{}', package ID '{}'",
self.from_id, package_name, package_id
))
})?;
let deps = dep_reqs.matches_for(version);
Ok((*name, deps))
}