Repository: paritytech/foundry-polkadot
Pull request #132: Fix `forge bind` with `--resolc`
Author: login: pkhry
Created: 2025-05-19T09:28:49Z | Merged: 2025-05-21T20:09:41Z

### Description 

Will use correct artifact.paths() for a given project now and look for artifacts in a correct directory. 

Related to #119 


Diff:
diff --git a/crates/config/src/revive.rs b/crates/config/src/revive.rs
index d29a2fae58bc3..0f22edef8797e 100644
--- a/crates/config/src/revive.rs
+++ b/crates/config/src/revive.rs
@@ -9,9 +9,6 @@ use crate::{Config, SolcReq};
 /// Filename for resolc cache
 pub const RESOLC_SOLIDITY_FILES_CACHE_FILENAME: &str = "resolc-solidity-files-cache.json";
 
-/// Directory for resolc artifacts
-pub const RESOLC_ARTIFACTS_DIR: &str = "resolc-out";
-
 pub const CONTRACT_SIZE_LIMIT: usize = 250_000;
 
 #[derive(Clone, Debug, PartialEq, Eq, Serialize, Default, Deserialize)]
@@ -41,13 +38,13 @@ impl ResolcConfig {
             .sources(&config.src)
             .tests(&config.test)
             .scripts(&config.script)
-            .artifacts(config.root.join(RESOLC_ARTIFACTS_DIR))
             .libs(config.libs.iter())
             .remappings(config.get_all_remappings())
             .allowed_path(&config.root)
             .allowed_paths(&config.libs)
             .allowed_paths(&config.allow_paths)
-            .include_paths(&config.include_paths);
+            .include_paths(&config.include_paths)
+            .artifacts(&config.out);
 
         builder.build_with_root(&config.root)
     }
diff --git a/crates/forge/src/args.rs b/crates/forge/src/args.rs
index bab0abda22d83..6c08b046a27fa 100644
--- a/crates/forge/src/args.rs
+++ b/crates/forge/src/args.rs
@@ -105,14 +105,10 @@ pub fn run_command(args: Forge) -> Result<()> {
             Ok(())
         }
         ForgeSubcommand::Clean { root } => {
-            let mut config = utils::load_config_with_root(root.as_deref())?;
+            let config = utils::load_config_with_root(root.as_deref())?;
             let project = config.project()?;
             config.cleanup(&project)?;
 
-            config.resolc.resolc_compile = true;
-            let resolc_project = config.project()?;
-            config.cleanup(&resolc_project)?;
-
             Ok(())
         }
         ForgeSubcommand::Snapshot(cmd) => {
diff --git a/crates/forge/src/cmd/bind.rs b/crates/forge/src/cmd/bind.rs
index b1f2aef0e5d31..151791baf409f 100644
--- a/crates/forge/src/cmd/bind.rs
+++ b/crates/forge/src/cmd/bind.rs
@@ -7,6 +7,7 @@ use foundry_common::{compile::ProjectCompiler, fs::json_files};
 use foundry_config::impl_figment_convert;
 use regex::Regex;
 use std::{
+    collections::BTreeSet,
     fs,
     path::{Path, PathBuf},
 };
@@ -112,31 +113,58 @@ pub struct BindArgs {
 }
 
 impl BindArgs {
-    pub fn run(self) -> Result<()> {
+    pub fn run(mut self) -> Result<()> {
         if self.ethers {
             eyre::bail!("`--ethers` bindings have been removed. Use `--alloy` (default) instead.");
         }
-
         if !self.skip_build {
             let project = self.build.project()?;
-            let _ = ProjectCompiler::new().compile(&project)?;
+            let old_builds: BTreeSet<String> = {
+                if let Ok(entries) = std::fs::read_dir(&project.paths.build_infos) {
+                    entries
+                        .filter_map(|x| x.ok())
+                        .filter_map(|f| {
+                            let path = f.path();
+                            if path.is_file() {
+                                path.file_stem().map(|x| x.to_string_lossy().into_owned())
+                            } else {
+                                None
+                            }
+                        })
+                        .collect()
+                } else {
+                    BTreeSet::new()
+                }
+            };
+            let output = ProjectCompiler::new().compile(&project)?;
+
+            let new_builds: BTreeSet<String> =
+                output.builds().map(|(key, _)| key).cloned().collect();
+
+            // if build_infos got overwritten => different compiler was used.
+            // in case of other possible errors(e.g. modified file we go as usual)
+            if old_builds.is_disjoint(&new_builds) {
+                self.overwrite = true;
+            }
         }
 
         let config = self.load_config()?;
-        let artifacts = config.out;
+        let project = config.project()?;
+
+        let artifacts = project.artifacts_path();
         let bindings_root = self.bindings.clone().unwrap_or_else(|| artifacts.join("bindings"));
 
         if bindings_root.exists() {
             if !self.overwrite {
                 sh_println!("Bindings found. Checking for consistency.")?;
-                return self.check_existing_bindings(&artifacts, &bindings_root);
+                return self.check_existing_bindings(artifacts, &bindings_root);
             }
 
             trace!(?artifacts, "Removing existing bindings");
             fs::remove_dir_all(&bindings_root)?;
         }
 
-        self.generate_bindings(&artifacts, &bindings_root)?;
+        self.generate_bindings(artifacts, &bindings_root)?;
 
         sh_println!("Bindings have been generated to {}", bindings_root.display())?;
         Ok(())
diff --git a/crates/forge/tests/cli/revive_cmd.rs b/crates/forge/tests/cli/revive_cmd.rs
index 6aa41463698f6..69d7095e28a81 100644
--- a/crates/forge/tests/cli/revive_cmd.rs
+++ b/crates/forge/tests/cli/revive_cmd.rs
@@ -25,7 +25,7 @@ forgetest_init!(can_clean_config, |prj, cmd| {
     // prj.update_config(|config| config.out = "custom-out".into());
     cmd.args(["build", "--resolc"]).assert_success();
 
-    let artifact = prj.root().join(format!("resolc-out/{TEMPLATE_TEST_CONTRACT_ARTIFACT_JSON}"));
+    let artifact = prj.artifacts().join(TEMPLATE_TEST_CONTRACT_ARTIFACT_JSON);
     assert!(artifact.exists());
 
     cmd.forge_fuse().arg("clean").assert_empty_stdout();
@@ -43,14 +43,14 @@ contract Foo {}
     .unwrap();
 
     // compile with solc
-    cmd.args(["build", "--out=resolc-out"]).assert_success().stdout_eq(str![[r#"
+    cmd.args(["build"]).assert_success().stdout_eq(str![[r#"
 [COMPILING_FILES] with [SOLC_VERSION]
 [SOLC_VERSION] [ELAPSED]
 Compiler run successful!
 
 "#]]);
 
-    let artifact = prj.root().join("resolc-out/");
+    let artifact = prj.artifacts();
     assert!(artifact.exists());
 
     // compile with resolc to the same output dir (resolc has hardcoded output dir)
@@ -62,7 +62,7 @@ Compiler run successful!
 "#]]);
 
     // compile again with solc to the same output dir
-    cmd.forge_fuse().args(["build", "--out=resolc-out"]).assert_success().stdout_eq(str![[r#"
+    cmd.forge_fuse().args(["build"]).assert_success().stdout_eq(str![[r#"
 [COMPILING_FILES] with [SOLC_VERSION]
 [SOLC_VERSION] [ELAPSED]
 Compiler run successful!
@@ -84,7 +84,7 @@ Compiler run successful!
 "#]
     ]);
 
-    let artifact_path = prj.root().join(format!("resolc-out/{CONTRACT_ARTIFACT_JSON}"));
+    let artifact_path = prj.artifacts().join(CONTRACT_ARTIFACT_JSON);
     let artifact: ConfigurableContractArtifact =
         foundry_compilers::utils::read_json_file(&artifact_path).unwrap();
     assert!(artifact.metadata.is_some());
@@ -100,8 +100,7 @@ Compiler run successful!
 
 "#]]);
 
-    let metadata_path =
-        prj.root().join(format!("resolc-out/{CONTRACT_ARTIFACT_BASE}.metadata.json"));
+    let metadata_path = prj.artifacts().join(format!("{CONTRACT_ARTIFACT_BASE}.metadata.json"));
     let _artifact: Metadata = foundry_compilers::utils::read_json_file(&metadata_path).unwrap();
 });
 
@@ -125,7 +124,7 @@ Compiler run successful!
 
 "#]]);
 
-    let artifact_path = prj.root().join(format!("resolc-out/{CONTRACT_ARTIFACT_JSON}"));
+    let artifact_path = prj.artifacts().join(CONTRACT_ARTIFACT_JSON);
     let artifact: ConfigurableContractArtifact =
         foundry_compilers::utils::read_json_file(&artifact_path).unwrap();
     assert!(artifact.metadata.is_some());
@@ -151,14 +150,13 @@ Compiler run successful!
 
 "#]]);
 
-    let metadata_path =
-        prj.root().join(format!("resolc-out/{CONTRACT_ARTIFACT_BASE}.metadata.json"));
+    let metadata_path = prj.artifacts().join(format!("{CONTRACT_ARTIFACT_BASE}.metadata.json"));
     let _artifact: Metadata = foundry_compilers::utils::read_json_file(&metadata_path).unwrap();
 
-    let iropt = prj.root().join(format!("resolc-out/{CONTRACT_ARTIFACT_BASE}.iropt"));
+    let iropt = prj.artifacts().join(format!("{CONTRACT_ARTIFACT_BASE}.iropt"));
     std::fs::read_to_string(iropt).unwrap();
 
-    let ir = prj.root().join(format!("resolc-out/{CONTRACT_ARTIFACT_BASE}.ir"));
+    let ir = prj.artifacts().join(format!("{CONTRACT_ARTIFACT_BASE}.ir"));
     std::fs::read_to_string(ir).unwrap();
 });
 
@@ -389,7 +387,7 @@ Compiler run successful!
 
 "#]]);
 
-    let artifact = prj.root().join(format!("resolc-out/{CONTRACT_ARTIFACT_JSON}"));
+    let artifact = prj.artifacts().join(CONTRACT_ARTIFACT_JSON);
     assert!(artifact.exists());
     let cache = prj.root().join("cache/resolc-solidity-files-cache.json");
     assert!(cache.exists());
@@ -892,8 +890,7 @@ forgetest!(inspect_custom_counter_method_identifiers_for_resolc, |prj, cmd| {
 forgetest!(can_bind_for_resolc, |prj, cmd| {
     init_prj(&prj);
 
-    //TODO: bind command is looking for artifacts in wrong directory
-    cmd.args(["bind", "--resolc", "--out", "resolc-out"]).assert_success().stdout_eq(str![[r#"
+    cmd.args(["bind", "--resolc"]).assert_success().stdout_eq(str![[r#"
 [COMPILING_FILES] with [RESOLC_VERSION]
 [RESOLC_VERSION] [ELAPSED]
 Compiler run successful!
@@ -927,13 +924,13 @@ forgetest!(can_bind_enum_modules_for_resolc, |prj, cmd| {
     .unwrap();
 
     //TODO: bind command is looking for artifacts in wrong directory
-    cmd.args(["bind", "--resolc", "--out", "resolc-out", "--select", "^Enum$"])
-        .assert_success()
-        .stdout_eq(str![[r#"[COMPILING_FILES] with [RESOLC_VERSION]
+    cmd.args(["bind", "--resolc", "--select", "^Enum$"]).assert_success().stdout_eq(str![[
+        r#"[COMPILING_FILES] with [RESOLC_VERSION]
 [RESOLC_VERSION] [ELAPSED]
 Compiler run successful!
 Generating bindings for 1 contracts
-Bindings have been generated to [..]"#]]);
+Bindings have been generated to [..]"#
+    ]]);
 });
 
 // Tests that direct import paths are handled correctly


Reviews:
user: login: smiasojed
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-19T09:53:51Z
user: login: pkhry
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-19T09:55:34Z
user: login: smiasojed
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T07:20:44Z
user: login: pkhry
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-21T07:25:50Z
user: login: smiasojed
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T07:47:59Z
user: login: pkhry
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-21T08:05:18Z
user: login: smiasojed
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T08:11:53Z
user: login: smiasojed
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T08:15:34Z
user: login: pkhry
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-21T08:26:46Z
user: login: pkhry
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-21T08:27:47Z
user: login: smiasojed
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T08:32:49Z
user: login: pkhry
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-21T08:36:53Z
user: login: smiasojed
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T09:11:53Z
user: login: smiasojed
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-21T09:12:16Z

Review comments:
diff_hunk: @@ -893,7 +893,7 @@ forgetest!(can_bind_for_resolc, |prj, cmd| {
     init_prj(&prj);
 
     //TODO: bind command is looking for artifacts in wrong directory
path: crates/forge/tests/cli/revive_cmd.rs
user: login: smiasojed
body: Please remove TODO
created_at: 2025-05-19T09:53:51Z
author_association: COLLABORATOR
diff_hunk: @@ -893,7 +893,7 @@ forgetest!(can_bind_for_resolc, |prj, cmd| {
     init_prj(&prj);
 
     //TODO: bind command is looking for artifacts in wrong directory
path: crates/forge/tests/cli/revive_cmd.rs
user: login: pkhry
body: done
created_at: 2025-05-19T09:55:34Z
author_association: NONE
diff_hunk: @@ -112,31 +113,58 @@ pub struct BindArgs {
 }
 
 impl BindArgs {
-    pub fn run(self) -> Result<()> {
+    pub fn run(mut self) -> Result<()> {
         if self.ethers {
             eyre::bail!("`--ethers` bindings have been removed. Use `--alloy` (default) instead.");
         }
-
         if !self.skip_build {
path: crates/forge/src/cmd/bind.rs
user: login: smiasojed
body: how it will work if I set skip build?
created_at: 2025-05-21T07:20:43Z
author_association: COLLABORATOR
diff_hunk: @@ -112,31 +113,58 @@ pub struct BindArgs {
 }
 
 impl BindArgs {
-    pub fn run(self) -> Result<()> {
+    pub fn run(mut self) -> Result<()> {
         if self.ethers {
             eyre::bail!("`--ethers` bindings have been removed. Use `--alloy` (default) instead.");
         }
-
         if !self.skip_build {
path: crates/forge/src/cmd/bind.rs
user: login: pkhry
body: it wont, it's a non-standard flag so i didn't try to account for this
created_at: 2025-05-21T07:25:50Z
author_association: NONE
diff_hunk: @@ -112,31 +113,58 @@ pub struct BindArgs {
 }
 
 impl BindArgs {
-    pub fn run(self) -> Result<()> {
+    pub fn run(mut self) -> Result<()> {
         if self.ethers {
             eyre::bail!("`--ethers` bindings have been removed. Use `--alloy` (default) instead.");
         }
-
         if !self.skip_build {
path: crates/forge/src/cmd/bind.rs
user: login: smiasojed
body: What do you mean by a non-standard flag? Is it possible to set it from the command line?
created_at: 2025-05-21T07:47:59Z
author_association: COLLABORATOR
diff_hunk: @@ -112,31 +113,58 @@ pub struct BindArgs {
 }
 
 impl BindArgs {
-    pub fn run(self) -> Result<()> {
+    pub fn run(mut self) -> Result<()> {
         if self.ethers {
             eyre::bail!("`--ethers` bindings have been removed. Use `--alloy` (default) instead.");
         }
-
         if !self.skip_build {
path: crates/forge/src/cmd/bind.rs
user: login: pkhry
body: as in normally you wouldn't pass it unless you know why are you doing it. by default it will recompile every time.
created_at: 2025-05-21T08:05:17Z
author_association: NONE
diff_hunk: @@ -41,7 +38,6 @@ impl ResolcConfig {
             .sources(&config.src)
             .tests(&config.test)
             .scripts(&config.script)
-            .artifacts(config.root.join(RESOLC_ARTIFACTS_DIR))
path: crates/config/src/revive.rs
user: login: smiasojed
body: should not we set  `.artifacts(&config.out)`?

created_at: 2025-05-21T08:11:53Z
author_association: COLLABORATOR
diff_hunk: @@ -112,31 +113,58 @@ pub struct BindArgs {
 }
 
 impl BindArgs {
-    pub fn run(self) -> Result<()> {
+    pub fn run(mut self) -> Result<()> {
         if self.ethers {
             eyre::bail!("`--ethers` bindings have been removed. Use `--alloy` (default) instead.");
         }
-
         if !self.skip_build {
             let project = self.build.project()?;
-            let _ = ProjectCompiler::new().compile(&project)?;
+            let old_builds: BTreeSet<String> = {
+                if let Ok(entries) = std::fs::read_dir(&project.paths.build_infos) {
+                    entries
+                        .filter_map(|x| x.ok())
+                        .filter_map(|f| {
+                            let path = f.path();
+                            if path.is_file() {
+                                path.file_stem().map(|x| x.to_string_lossy().into_owned())
+                            } else {
+                                None
+                            }
+                        })
+                        .collect()
+                } else {
+                    BTreeSet::new()
+                }
+            };
+            let output = ProjectCompiler::new().compile(&project)?;
+
+            let new_builds: BTreeSet<String> =
+                output.builds().map(|(key, _)| key).cloned().collect();
+
+            // if build_infos got overwritten => different compiler was used.
+            // in case of other possible errors(e.g. modified file we go as usual)
+            if old_builds.is_disjoint(&new_builds) {
+                self.overwrite = true;
+            }
         }
 
         let config = self.load_config()?;
-        let artifacts = config.out;
path: crates/forge/src/cmd/bind.rs
user: login: smiasojed
body: why does not config.out work? 
created_at: 2025-05-21T08:15:33Z
author_association: COLLABORATOR
diff_hunk: @@ -41,7 +38,6 @@ impl ResolcConfig {
             .sources(&config.src)
             .tests(&config.test)
             .scripts(&config.script)
-            .artifacts(config.root.join(RESOLC_ARTIFACTS_DIR))
path: crates/config/src/revive.rs
user: login: pkhry
body: added it back, but it would've been set automatically depending on the project settings[here](            .artifacts(&config.out))?

created_at: 2025-05-21T08:26:46Z
author_association: NONE
diff_hunk: @@ -112,31 +113,58 @@ pub struct BindArgs {
 }
 
 impl BindArgs {
-    pub fn run(self) -> Result<()> {
+    pub fn run(mut self) -> Result<()> {
         if self.ethers {
             eyre::bail!("`--ethers` bindings have been removed. Use `--alloy` (default) instead.");
         }
-
         if !self.skip_build {
             let project = self.build.project()?;
-            let _ = ProjectCompiler::new().compile(&project)?;
+            let old_builds: BTreeSet<String> = {
+                if let Ok(entries) = std::fs::read_dir(&project.paths.build_infos) {
+                    entries
+                        .filter_map(|x| x.ok())
+                        .filter_map(|f| {
+                            let path = f.path();
+                            if path.is_file() {
+                                path.file_stem().map(|x| x.to_string_lossy().into_owned())
+                            } else {
+                                None
+                            }
+                        })
+                        .collect()
+                } else {
+                    BTreeSet::new()
+                }
+            };
+            let output = ProjectCompiler::new().compile(&project)?;
+
+            let new_builds: BTreeSet<String> =
+                output.builds().map(|(key, _)| key).cloned().collect();
+
+            // if build_infos got overwritten => different compiler was used.
+            // in case of other possible errors(e.g. modified file we go as usual)
+            if old_builds.is_disjoint(&new_builds) {
+                self.overwrite = true;
+            }
         }
 
         let config = self.load_config()?;
-        let artifacts = config.out;
path: crates/forge/src/cmd/bind.rs
user: login: pkhry
body: i feel like `project.artifacts` is more semantically correct because `config.out` is global value and each project might have their unique settings set and use a different compiler
created_at: 2025-05-21T08:27:47Z
author_association: NONE
diff_hunk: @@ -41,7 +38,6 @@ impl ResolcConfig {
             .sources(&config.src)
             .tests(&config.test)
             .scripts(&config.script)
-            .artifacts(config.root.join(RESOLC_ARTIFACTS_DIR))
path: crates/config/src/revive.rs
user: login: smiasojed
body: the link does not work on my side
created_at: 2025-05-21T08:32:49Z
author_association: COLLABORATOR
diff_hunk: @@ -41,7 +38,6 @@ impl ResolcConfig {
             .sources(&config.src)
             .tests(&config.test)
             .scripts(&config.script)
-            .artifacts(config.root.join(RESOLC_ARTIFACTS_DIR))
path: crates/config/src/revive.rs
user: login: pkhry
body: here's non borked one [click me](https://github.com/paritytech/foundry-revive-compiler/blob/master/crates/compilers/src/config.rs#L895)
created_at: 2025-05-21T08:36:53Z
author_association: NONE
diff_hunk: @@ -112,31 +113,58 @@ pub struct BindArgs {
 }
 
 impl BindArgs {
-    pub fn run(self) -> Result<()> {
+    pub fn run(mut self) -> Result<()> {
         if self.ethers {
             eyre::bail!("`--ethers` bindings have been removed. Use `--alloy` (default) instead.");
         }
-
         if !self.skip_build {
             let project = self.build.project()?;
-            let _ = ProjectCompiler::new().compile(&project)?;
+            let old_builds: BTreeSet<String> = {
+                if let Ok(entries) = std::fs::read_dir(&project.paths.build_infos) {
+                    entries
+                        .filter_map(|x| x.ok())
+                        .filter_map(|f| {
+                            let path = f.path();
+                            if path.is_file() {
+                                path.file_stem().map(|x| x.to_string_lossy().into_owned())
+                            } else {
+                                None
+                            }
+                        })
+                        .collect()
+                } else {
+                    BTreeSet::new()
+                }
+            };
+            let output = ProjectCompiler::new().compile(&project)?;
+
+            let new_builds: BTreeSet<String> =
+                output.builds().map(|(key, _)| key).cloned().collect();
+
+            // if build_infos got overwritten => different compiler was used.
+            // in case of other possible errors(e.g. modified file we go as usual)
+            if old_builds.is_disjoint(&new_builds) {
+                self.overwrite = true;
+            }
         }
 
         let config = self.load_config()?;
-        let artifacts = config.out;
path: crates/forge/src/cmd/bind.rs
user: login: smiasojed
body: if the original code is working fine I would prefer to keep the original code
created_at: 2025-05-21T09:11:53Z
author_association: COLLABORATOR

PR comments:
user: login: smiasojed
created_at: 2025-05-19T09:57:01Z
body: Why do not you consider removing `resolc-out` hardcoded output path. I think it should help


author_association: COLLABORATOR
user: login: pkhry
created_at: 2025-05-19T09:59:25Z
body: > Why do not you consider removing `resolc-out` hardcoded output path. I think it should help

it wouldn't really as artifact outputs are set per compiler basis so i think hardcoded output-selection is a bit of an ortogonal issue
author_association: NONE
user: login: smiasojed
created_at: 2025-05-19T10:12:29Z
body: > > Why do not you consider removing `resolc-out` hardcoded output path. I think it should help
> 
> it wouldn't really as artifact outputs are set per compiler basis so i think hardcoded output-selection is a bit of an ortogonal issue

I think, the main issue is that our output customization, which we have for resolc is not propagated correctly to config.out

Please see:

```
../foundry-polkadot-sm/target/debug/forge config --resolc

[profile.default]
src = "src"
test = "test"
script = "script"
out = "out"
```
author_association: COLLABORATOR
user: login: pkhry
created_at: 2025-05-19T10:32:28Z
body: > > > Why do not you consider removing `resolc-out` hardcoded output path. I think it should help
> > 
> > 
> > it wouldn't really as artifact outputs are set per compiler basis so i think hardcoded output-selection is a bit of an ortogonal issue
> 
> I think, the main issue is that our output customization, which we have for resolc is not propagated correctly to config.out
> 
> Please see:
> 
> ```
> ../foundry-polkadot-sm/target/debug/forge config --resolc
> 
> [profile.default]
> src = "src"
> test = "test"
> script = "script"
> out = "out"
> ```

and it shouldn't i guess as paths are immutable and when switching compilers we would have to modify config.out every time. but if the intention is to just reuse the same `out` dir as global config - then yeah, it makes much more sense to remove `resolc-out`

EDIT: 
removing `resolc-out` might have unintended consequences as when using `forge bind` and attempting to generate `bindings` with wrong compiler output will return an error that's hard to account for that will say: 
```bash
Bindings found. Checking for consistency.
Checking bindings for 3 contracts
Error: File contents do not match expected contents for "<path>/out/bindings/src/best.rs"
```
so we will not know that we need to recompile with the proper compiler and then re-run the bind command again and i don't understand how to detect this error except for loading the caches and checking which `cache` is being used in the `out` directory right now before running the command. Note this might be needed to extend to other commands that interact with `out` dir in any way shape or form
author_association: NONE
user: login: smiasojed
created_at: 2025-05-19T11:01:06Z
body: It think we end up with the same issue when someone use `forge bind --out resolc-out`
author_association: COLLABORATOR
user: login: pkhry
created_at: 2025-05-20T11:28:37Z
body: removed `resolc-out` completely
author_association: NONE
user: login: smiasojed
created_at: 2025-05-20T13:03:45Z
body: Do we still have the issue which you have described after last changes or not?
author_association: COLLABORATOR
user: login: pkhry
created_at: 2025-05-20T13:14:36Z
body: > Do we still have the issue which you have described after last changes or not?

yeah, it will persist.
author_association: NONE
user: login: pkhry
created_at: 2025-05-20T15:35:45Z
body: > Do we still have the issue which you have described after last changes or not?

ok, now we do a forced recompile if we switched the compilers.
author_association: NONE