Skip to content

Commit f24e37a

Browse files
committed
wip
1 parent a9098d0 commit f24e37a

File tree

8 files changed

+111
-21
lines changed

8 files changed

+111
-21
lines changed

crates/compilers/src/cache.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ impl<S: CompilerSettings> CompilerCache<S> {
163163
.entries()
164164
.flat_map(|e| e.artifacts.values())
165165
.flat_map(|a| a.values())
166+
.flat_map(|a| a.values())
166167
.any(|a| a.build_id == *build_id)
167168
{
168169
outdated.push(build_id.to_owned());

crates/compilers/src/compilers/mod.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ pub mod solc;
2424
pub mod vyper;
2525
pub use vyper::*;
2626

27+
mod restrictions;
28+
pub use restrictions::{CompilerSettingsRestrictions, RestrictionsWithVersion};
29+
2730
/// A compiler version is either installed (available locally) or can be downloaded, from the remote
2831
/// endpoint
2932
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
@@ -61,10 +64,6 @@ impl fmt::Display for CompilerVersion {
6164
}
6265
}
6366

64-
pub trait CompilerSettingsRestrictions: Debug + Sync + Send + Clone + Default {
65-
fn merge(&mut self, other: &Self);
66-
}
67-
6867
/// Compilation settings including evm_version, output_selection, etc.
6968
pub trait CompilerSettings:
7069
Default + Serialize + DeserializeOwned + Clone + Debug + Send + Sync + 'static

crates/compilers/src/compilers/multi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::{
2+
restrictions::CompilerSettingsRestrictions,
23
solc::{SolcCompiler, SolcSettings, SolcVersionedInput, SOLC_EXTENSIONS},
34
vyper::{
45
input::VyperVersionedInput, parser::VyperParsedSource, Vyper, VyperLanguage,
@@ -12,7 +13,6 @@ use crate::{
1213
resolver::parse::SolData,
1314
settings::VyperRestrictions,
1415
solc::SolcRestrictions,
15-
CompilerSettingsRestrictions,
1616
};
1717
use foundry_compilers_artifacts::{
1818
error::SourceLocation,
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use std::{
2+
fmt::Debug,
3+
ops::{Deref, DerefMut},
4+
};
5+
6+
use semver::VersionReq;
7+
8+
pub trait CompilerSettingsRestrictions: Debug + Sync + Send + Clone + Default {
9+
fn merge(&mut self, other: &Self);
10+
}
11+
12+
/// Combines [CompilerVersionRestriction] with a restrictions on compiler versions for a given
13+
/// source file.
14+
#[derive(Debug, Clone, Default)]
15+
pub struct RestrictionsWithVersion<T> {
16+
pub version: Option<VersionReq>,
17+
pub settings: T,
18+
}
19+
20+
impl<T> Deref for RestrictionsWithVersion<T> {
21+
type Target = T;
22+
23+
fn deref(&self) -> &Self::Target {
24+
&self.settings
25+
}
26+
}
27+
28+
impl<T> DerefMut for RestrictionsWithVersion<T> {
29+
fn deref_mut(&mut self) -> &mut Self::Target {
30+
&mut self.settings
31+
}
32+
}

crates/compilers/src/compilers/solc/mod.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use super::{
2-
CompilationError, Compiler, CompilerInput, CompilerOutput, CompilerSettings, CompilerVersion,
3-
Language, ParsedSource,
2+
restrictions::CompilerSettingsRestrictions, CompilationError, Compiler, CompilerInput,
3+
CompilerOutput, CompilerSettings, CompilerVersion, Language, ParsedSource,
44
};
5-
use crate::{resolver::parse::SolData, CompilerSettingsRestrictions};
5+
use crate::resolver::parse::SolData;
66
pub use foundry_compilers_artifacts::SolcLanguage;
77
use foundry_compilers_artifacts::{
88
error::SourceLocation,
99
output_selection::OutputSelection,
1010
remappings::Remapping,
11+
serde_helpers::display_from_str_opt,
1112
sources::{Source, Sources},
1213
Error, EvmVersion, Settings, Severity, SolcInput,
1314
};
@@ -190,9 +191,11 @@ impl DerefMut for SolcSettings {
190191
}
191192
}
192193

193-
#[derive(Debug, Clone, Copy, Default)]
194+
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, Eq, PartialEq)]
194195
pub struct EvmVersionRestriction {
196+
#[serde(default, with = "display_from_str_opt", skip_serializing_if = "Option::is_none")]
195197
pub min_evm_version: Option<EvmVersion>,
198+
#[serde(default, with = "display_from_str_opt", skip_serializing_if = "Option::is_none")]
196199
pub max_evm_version: Option<EvmVersion>,
197200
}
198201

@@ -226,6 +229,8 @@ impl EvmVersionRestriction {
226229
pub struct SolcRestrictions {
227230
pub evm_version: EvmVersionRestriction,
228231
pub via_ir: Option<bool>,
232+
pub min_optimizer_runs: Option<usize>,
233+
pub max_optimizer_runs: Option<usize>,
229234
}
230235

231236
impl CompilerSettingsRestrictions for SolcRestrictions {
@@ -305,6 +310,12 @@ impl CompilerSettings for SolcSettings {
305310
satisfies &= restrictions.evm_version.satisfies(self.evm_version);
306311
satisfies &=
307312
restrictions.via_ir.map_or(true, |via_ir| via_ir == self.via_ir.unwrap_or_default());
313+
satisfies &= restrictions
314+
.min_optimizer_runs
315+
.map_or(true, |min| self.optimizer.runs.map_or(false, |runs| runs >= min));
316+
satisfies &= restrictions
317+
.max_optimizer_runs
318+
.map_or(true, |max| self.optimizer.runs.map_or(false, |runs| runs <= max));
308319

309320
satisfies
310321
}

crates/compilers/src/compilers/vyper/settings.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use std::{collections::BTreeSet, path::PathBuf};
22

33
pub use crate::artifacts::vyper::VyperSettings;
44
use crate::{
5-
compilers::CompilerSettings, solc::EvmVersionRestriction, CompilerSettingsRestrictions,
5+
compilers::{restrictions::CompilerSettingsRestrictions, CompilerSettings},
6+
solc::EvmVersionRestriction,
67
};
78
use foundry_compilers_artifacts::output_selection::OutputSelection;
89

crates/compilers/src/lib.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ pub struct Project<C: Compiler = MultiCompiler, T: ArtifactOutput = Configurable
7878
/// Additional settings for cases when default compiler settings are not enough to cover all
7979
/// possible restrictions.
8080
pub additional_settings: BTreeMap<String, C::Settings>,
81-
pub restrictions: BTreeMap<PathBuf, <C::Settings as CompilerSettings>::Restrictions>,
81+
pub restrictions:
82+
BTreeMap<PathBuf, RestrictionsWithVersion<<C::Settings as CompilerSettings>::Restrictions>>,
8283
/// Whether caching is enabled
8384
pub cached: bool,
8485
/// Whether to output build information with each solc call.
@@ -455,6 +456,9 @@ pub struct ProjectBuilder<C: Compiler = MultiCompiler, T: ArtifactOutput = Confi
455456
paths: Option<ProjectPathsConfig<C::Language>>,
456457
/// How solc invocation should be configured.
457458
settings: Option<C::Settings>,
459+
additional_settings: BTreeMap<String, C::Settings>,
460+
restrictions:
461+
BTreeMap<PathBuf, RestrictionsWithVersion<<C::Settings as CompilerSettings>::Restrictions>>,
458462
/// Whether caching is enabled, default is true.
459463
cached: bool,
460464
/// Whether to output build information with each solc call.
@@ -495,6 +499,8 @@ impl<C: Compiler, T: ArtifactOutput> ProjectBuilder<C, T> {
495499
solc_jobs: None,
496500
settings: None,
497501
sparse_output: None,
502+
additional_settings: BTreeMap::new(),
503+
restrictions: BTreeMap::new(),
498504
}
499505
}
500506

@@ -619,6 +625,24 @@ impl<C: Compiler, T: ArtifactOutput> ProjectBuilder<C, T> {
619625
self
620626
}
621627

628+
#[must_use]
629+
pub fn additional_settings(mut self, additional: BTreeMap<String, C::Settings>) -> Self {
630+
self.additional_settings = additional;
631+
self
632+
}
633+
634+
#[must_use]
635+
pub fn restrictions(
636+
mut self,
637+
restrictions: BTreeMap<
638+
PathBuf,
639+
RestrictionsWithVersion<<C::Settings as CompilerSettings>::Restrictions>,
640+
>,
641+
) -> Self {
642+
self.restrictions = restrictions;
643+
self
644+
}
645+
622646
/// Set arbitrary `ArtifactOutputHandler`
623647
pub fn artifacts<A: ArtifactOutput>(self, artifacts: A) -> ProjectBuilder<C, A> {
624648
let Self {
@@ -634,12 +658,16 @@ impl<C: Compiler, T: ArtifactOutput> ProjectBuilder<C, T> {
634658
ignored_file_paths,
635659
settings,
636660
sparse_output,
661+
additional_settings,
662+
restrictions,
637663
..
638664
} = self;
639665
ProjectBuilder {
640666
paths,
641667
cached,
642668
no_artifacts,
669+
additional_settings,
670+
restrictions,
643671
offline,
644672
slash_paths,
645673
artifacts,
@@ -668,6 +696,8 @@ impl<C: Compiler, T: ArtifactOutput> ProjectBuilder<C, T> {
668696
slash_paths,
669697
settings,
670698
sparse_output,
699+
additional_settings,
700+
restrictions,
671701
} = self;
672702

673703
let mut paths = paths.map(Ok).unwrap_or_else(ProjectPathsConfig::current_hardhat)?;
@@ -694,8 +724,8 @@ impl<C: Compiler, T: ArtifactOutput> ProjectBuilder<C, T> {
694724
slash_paths,
695725
settings: settings.unwrap_or_default(),
696726
sparse_output,
697-
additional_settings: Default::default(),
698-
restrictions: Default::default(),
727+
additional_settings,
728+
restrictions,
699729
})
700730
}
701731
}

crates/compilers/src/resolver/mod.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -580,10 +580,20 @@ impl<L: Language, D: ParsedSource<Language = L>> Graph<D> {
580580
}
581581

582582
/// Filters incompatible versions from the `candidates`.
583-
fn retain_compatible_versions(&self, idx: usize, candidates: &mut Vec<&CompilerVersion>) {
583+
fn retain_compatible_versions<C: Compiler, T: ArtifactOutput>(
584+
&self,
585+
idx: usize,
586+
project: &Project<C, T>,
587+
candidates: &mut Vec<&CompilerVersion>,
588+
) {
584589
let nodes: HashSet<_> = self.node_ids(idx).collect();
585590
for node in nodes {
586-
if let Some(req) = &self.node(node).data.version_req() {
591+
let node = self.node(node);
592+
if let Some(req) = node.data.version_req() {
593+
candidates.retain(|v| req.matches(v.as_ref()));
594+
}
595+
if let Some(req) = project.restrictions.get(&node.path).and_then(|r| r.version.as_ref())
596+
{
587597
candidates.retain(|v| req.matches(v.as_ref()));
588598
}
589599
if candidates.is_empty() {
@@ -604,7 +614,7 @@ impl<L: Language, D: ParsedSource<Language = L>> Graph<D> {
604614
let node = self.node(node);
605615
if let Some(requirement) = project.restrictions.get(&node.path) {
606616
candidates
607-
.retain(|(_, (_, settings))| settings.satisfies_restrictions(requirement));
617+
.retain(|(_, (_, settings))| settings.satisfies_restrictions(&*requirement));
608618
}
609619
if candidates.is_empty() {
610620
// nothing to filter anymore
@@ -677,7 +687,7 @@ impl<L: Language, D: ParsedSource<Language = L>> Graph<D> {
677687
let mut candidates = all_versions.iter().collect::<Vec<_>>();
678688
// remove all incompatible versions from the candidates list by checking the node
679689
// and all its imports
680-
self.retain_compatible_versions(idx, &mut candidates);
690+
self.retain_compatible_versions(idx, project, &mut candidates);
681691

682692
if candidates.is_empty() && !erroneous_nodes.contains(&idx) {
683693
// check if the version is even valid
@@ -759,14 +769,20 @@ impl<L: Language, D: ParsedSource<Language = L>> Graph<D> {
759769
for (version, nodes) in versions {
760770
let mut profile_to_nodes = HashMap::new();
761771
for idx in nodes {
772+
println!("resolving {:?}", self.node(idx).path.display());
762773
let mut profile_candidates =
763774
project.settings_profiles().enumerate().collect::<Vec<_>>();
764775
self.retain_compatible_profiles(idx, project, &mut profile_candidates);
765776

766-
profile_to_nodes
767-
.entry(profile_candidates[0].0)
768-
.or_insert_with(Vec::new)
769-
.push(idx);
777+
if let Some((profile_idx, _)) = profile_candidates.first() {
778+
profile_to_nodes.entry(*profile_idx).or_insert_with(Vec::new).push(idx);
779+
} else {
780+
panic!(
781+
"failed to resolve settings for node {}",
782+
self.node(idx).path.display()
783+
);
784+
}
785+
println!("resolved");
770786
}
771787
versioned_sources.insert(version, profile_to_nodes);
772788
}

0 commit comments

Comments
 (0)