Skip to content

Commit 353e85a

Browse files
authored
fix: make sources' paths absolute (#312)
Cache entries are keyed by absolute path relative to project root, but it's possible to construct and pass in Sources from a relative path, such as CLI argument in `forge lint`/`forge eip712`... In these cases the path will be relative and will always be a cache miss. This includes the path's imports, which get resolved as relative to the initial path rather than root now with Solar. Make all paths in Sources absolute when constructing Graph so that this change propagates through the entire compilation process. I couldn't find a reproducer in today's stable/nightly Foundry, however making `config.solar_project()` use `project()` instead of `ephemeral_project()` will reproduce the behavior explained above. With this change, `solar_project` will almost never call to solc.
1 parent 0073f15 commit 353e85a

File tree

4 files changed

+19
-10
lines changed

4 files changed

+19
-10
lines changed

crates/artifacts/solc/src/sources.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ impl Sources {
2222
Self::default()
2323
}
2424

25+
/// Joins all paths relative to `root`.
26+
pub fn make_absolute(&mut self, root: &Path) {
27+
self.0 = std::mem::take(&mut self.0)
28+
.into_iter()
29+
.map(|(path, source)| (root.join(path), source))
30+
.collect();
31+
}
32+
2533
/// Returns `true` if no sources should have optimized output selection.
2634
pub fn all_dirty(&self) -> bool {
2735
self.0.values().all(|s| s.is_dirty())
@@ -169,7 +177,7 @@ impl Source {
169177
/// Recursively finds all source files under the given dir path and reads them all
170178
#[cfg(feature = "walkdir")]
171179
pub fn read_all_from(dir: &Path, extensions: &[&str]) -> Result<Sources, SolcIoError> {
172-
Self::read_all_files(utils::source_files(dir, extensions))
180+
Self::read_all(utils::source_files_iter(dir, extensions))
173181
}
174182

175183
/// Recursively finds all solidity and yul files under the given dir path and reads them all
@@ -178,14 +186,12 @@ impl Source {
178186
Self::read_all_from(dir, utils::SOLC_EXTENSIONS)
179187
}
180188

181-
/// Reads all source files of the given vec
182-
///
183-
/// Depending on the len of the vec it will try to read the files in parallel
189+
/// Reads all source files of the given list.
184190
pub fn read_all_files(files: Vec<PathBuf>) -> Result<Sources, SolcIoError> {
185191
Self::read_all(files)
186192
}
187193

188-
/// Reads all files
194+
/// Reads all of the given files.
189195
#[instrument(name = "Source::read_all", skip_all)]
190196
pub fn read_all<T, I>(files: I) -> Result<Sources, SolcIoError>
191197
where

crates/compilers/src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ impl<L: Language> ProjectPathsConfig<L> {
616616

617617
/// Returns the combined set of `Self::read_sources` + `Self::read_tests` + `Self::read_scripts`
618618
pub fn read_input_files(&self) -> Result<Sources> {
619-
Ok(Source::read_all_files(self.input_files())?)
619+
Ok(Source::read_all(self.input_files_iter())?)
620620
}
621621
}
622622

crates/compilers/src/flatten.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ impl Flattener {
209209

210210
let output = output.compiler_output;
211211

212-
let sources = Source::read_all_files(vec![target.to_path_buf()])?;
212+
let sources = Source::read_all([target.to_path_buf()])?;
213213
let graph = Graph::<C::Parser>::resolve_sources(&project.paths, sources)?;
214214

215215
let ordered_sources = collect_ordered_deps(target, &project.paths, &graph)?;

crates/compilers/src/resolver/mod.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,9 @@ impl<P: SourceParser> Graph<P> {
400400
Ok(())
401401
}
402402

403+
// The cache relies on the absolute paths relative to the project root as cache keys.
404+
sources.make_absolute(&paths.root);
405+
403406
let mut parser = P::new(paths.with_language_ref());
404407

405408
// we start off by reading all input files, which includes all solidity files from the
@@ -566,14 +569,14 @@ impl<P: SourceParser> Graph<P> {
566569
let mut versioned_sources = Vec::with_capacity(versioned_nodes.len());
567570

568571
for (version, profile_to_nodes) in versioned_nodes {
569-
for (profile_idx, input_node_indixies) in profile_to_nodes {
572+
for (profile_idx, input_node_indexes) in profile_to_nodes {
570573
let mut sources = Sources::new();
571574

572575
// all input nodes will be processed
573-
let mut processed_sources = input_node_indixies.iter().copied().collect();
576+
let mut processed_sources = input_node_indexes.iter().copied().collect();
574577

575578
// we only process input nodes (from sources, tests for example)
576-
for idx in input_node_indixies {
579+
for idx in input_node_indexes {
577580
// insert the input node in the sources set and remove it from the available
578581
// set
579582
let (path, source) =

0 commit comments

Comments
 (0)