fix(solc): allow cyclic imports (#766)

This commit is contained in:
Matthias Seitz 2022-01-07 01:12:33 +01:00 committed by GitHub
parent 88b342287a
commit eeb2a84df4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 16 additions and 8 deletions

View File

@ -268,21 +268,22 @@ impl Graph {
traversed: &mut std::collections::HashSet<(usize, usize)>, traversed: &mut std::collections::HashSet<(usize, usize)>,
) -> std::result::Result<(), String> { ) -> std::result::Result<(), String> {
let node = self.node(idx); let node = self.node(idx);
if let Some(ref req) = node.data.version_req { if let Some(ref req) = node.data.version_req {
candidates.retain(|v| req.matches(v.as_ref())); candidates.retain(|v| req.matches(v.as_ref()));
} }
for dep in self.imported_nodes(idx).iter().copied() { for dep in self.imported_nodes(idx).iter().copied() {
// check for circular deps which would result in endless recursion SO here // check for circular deps which would result in endless recursion SO here
// a circular dependency exists, if there was already a `dependency imports current // a circular dependency exists, if there was already a `dependency imports current
// node` relationship in the traversed path // node` relationship in the traversed path we skip this node
if traversed.contains(&(dep, idx)) {
let mut msg = String::new();
self.format_imports_list(dep, &mut msg).unwrap();
return Err(format!("Encountered circular dependencies in:\n{}", msg))
}
traversed.insert((idx, dep)); traversed.insert((idx, dep));
if traversed.contains(&(dep, idx)) {
tracing::warn!(
"Detected cyclic imports {} <-> {}",
utils::source_name(&self.nodes[idx].path, &self.root).display(),
utils::source_name(&self.nodes[dep].path, &self.root).display()
);
continue
}
self.retain_compatible_versions(dep, candidates, traversed)?; self.retain_compatible_versions(dep, candidates, traversed)?;
} }
Ok(()) Ok(())
@ -308,6 +309,7 @@ impl Graph {
&self, &self,
offline: bool, offline: bool,
) -> Result<HashMap<crate::SolcVersion, Vec<usize>>> { ) -> Result<HashMap<crate::SolcVersion, Vec<usize>>> {
tracing::trace!("resolving input node versions");
// this is likely called by an application and will be eventually printed so we don't exit // this is likely called by an application and will be eventually printed so we don't exit
// on first error, instead gather all the errors and return a bundled error message instead // on first error, instead gather all the errors and return a bundled error message instead
let mut errors = Vec::new(); let mut errors = Vec::new();
@ -349,8 +351,14 @@ impl Graph {
} }
if errors.is_empty() { if errors.is_empty() {
tracing::trace!(
"resolved {} versions {:?}",
versioned_nodes.len(),
versioned_nodes.keys()
);
Ok(versioned_nodes) Ok(versioned_nodes)
} else { } else {
tracing::error!("failed to resolve versions");
Err(crate::error::SolcError::msg(errors.join("\n"))) Err(crate::error::SolcError::msg(errors.join("\n")))
} }
} }