diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 641342f9b..e8710d014 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,15 +21,17 @@ jobs: fail-fast: false matrix: os: ["ubuntu-latest", "macos-latest", "windows-latest"] - rust: ["stable", "1.70"] + rust: ["stable", "1.83"] flags: ["", "--all-features"] exclude: # Skip because some features have higher MSRV. - - rust: "1.70" # MSRV + - rust: "1.83" # MSRV flags: "--all-features" steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} - name: Install test binaries shell: bash run: ./.github/scripts/install_test_binaries.sh @@ -38,11 +40,7 @@ jobs: - uses: Swatinem/rust-cache@v2 with: cache-on-failure: true - - name: build - if: matrix.rust == '1.70' # MSRV - run: cargo build --workspace ${{ matrix.flags }} - name: test - if: matrix.rust != '1.70' # MSRV shell: bash run: cargo nextest run ${{ matrix.flags }} --retries 2 diff --git a/Cargo.toml b/Cargo.toml index 5b7879136..d40d4d9c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ resolver = "2" [workspace.package] authors = ["Foundry Maintainers"] version = "0.12.3" -rust-version = "1.70" +rust-version = "1.83" readme = "README.md" license = "MIT OR Apache-2.0" repository = "https://github.com/foundry-rs/compilers" diff --git a/README.md b/README.md index 88cb13f50..70e1f88f0 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ When updating this, also update: Foundry Compilers will keep a rolling MSRV (minimum supported rust version) policy of **at least** 6 months. When increasing the MSRV, the new Rust version must have been -released at least six months ago. The current MSRV is 1.70.0. +released at least six months ago. The current MSRV is 1.83.0. Note that the MSRV is not increased automatically, and only as part of a minor release. diff --git a/clippy.toml b/clippy.toml index 5d37e5d80..f234c9014 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1 @@ -msrv = "1.70" +msrv = "1.83" diff --git a/crates/artifacts/solc/src/error.rs b/crates/artifacts/solc/src/error.rs index bdde31d08..78453cd6f 100644 --- a/crates/artifacts/solc/src/error.rs +++ b/crates/artifacts/solc/src/error.rs @@ -150,9 +150,11 @@ impl fmt::Display for Error { // unless it also contains a source location, in which case the entire error message is an // old style error message, like: // path/to/file:line:column: ErrorType: message - if lines.clone().next().map_or(false, |l| { - l.contains(short_msg) && l.bytes().filter(|b| *b == b':').count() < 3 - }) { + if lines + .clone() + .next() + .is_some_and(|l| l.contains(short_msg) && l.bytes().filter(|b| *b == b':').count() < 3) + { let _ = lines.next(); } diff --git a/crates/artifacts/solc/src/lib.rs b/crates/artifacts/solc/src/lib.rs index a04da256b..6437181d0 100644 --- a/crates/artifacts/solc/src/lib.rs +++ b/crates/artifacts/solc/src/lib.rs @@ -110,9 +110,9 @@ impl SolcInput { let mut yul_sources = Sources::new(); for (file, source) in sources { - if file.extension().map_or(false, |e| e == "yul") { + if file.extension().is_some_and(|e| e == "yul") { yul_sources.insert(file, source); - } else if file.extension().map_or(false, |e| e == "sol") { + } else if file.extension().is_some_and(|e| e == "sol") { solidity_sources.insert(file, source); } } diff --git a/crates/artifacts/solc/src/output_selection.rs b/crates/artifacts/solc/src/output_selection.rs index e39e28d05..99beb3e0b 100644 --- a/crates/artifacts/solc/src/output_selection.rs +++ b/crates/artifacts/solc/src/output_selection.rs @@ -149,9 +149,9 @@ impl OutputSelection { /// TODO: correctly process wildcard keys to reduce false negatives pub fn is_subset_of(&self, other: &Self) -> bool { self.0.iter().all(|(file, selection)| { - other.0.get(file).map_or(false, |other_selection| { + other.0.get(file).is_some_and(|other_selection| { selection.iter().all(|(contract, outputs)| { - other_selection.get(contract).map_or(false, |other_outputs| { + other_selection.get(contract).is_some_and(|other_outputs| { outputs.iter().all(|output| other_outputs.contains(output)) }) }) diff --git a/crates/artifacts/vyper/src/input.rs b/crates/artifacts/vyper/src/input.rs index 7b99b79ae..9b1b17d74 100644 --- a/crates/artifacts/vyper/src/input.rs +++ b/crates/artifacts/vyper/src/input.rs @@ -22,7 +22,7 @@ impl VyperInput { let mut interfaces = Sources::new(); for (path, content) in sources { - if path.extension().map_or(false, |ext| ext == VYPER_INTERFACE_EXTENSION) { + if path.extension().is_some_and(|ext| ext == VYPER_INTERFACE_EXTENSION) { // Interface .vyi files should be removed from the output selection. settings.output_selection.0.remove(path.to_string_lossy().as_ref()); interfaces.insert(path, content); diff --git a/crates/compilers/src/cache.rs b/crates/compilers/src/cache.rs index 21a738d7e..17777e66e 100644 --- a/crates/compilers/src/cache.rs +++ b/crates/compilers/src/cache.rs @@ -616,7 +616,7 @@ impl GroupedSources { /// Returns true if the file was included with the given version. pub fn contains(&self, file: &Path, version: &Version) -> bool { - self.inner.get(file).map_or(false, |versions| versions.contains(version)) + self.inner.get(file).is_some_and(|versions| versions.contains(version)) } } @@ -783,9 +783,7 @@ impl ArtifactsCacheInner<'_, T, C> { let mut dirty_profiles = HashSet::new(); for (profile, settings) in &self.cache.profiles { - if !existing_profiles - .get(profile.as_str()) - .map_or(false, |p| p.can_use_cached(settings)) + if !existing_profiles.get(profile.as_str()).is_some_and(|p| p.can_use_cached(settings)) { trace!("dirty profile: {}", profile); dirty_profiles.insert(profile.clone()); diff --git a/crates/compilers/src/compile/output/mod.rs b/crates/compilers/src/compile/output/mod.rs index 4c2eb9c44..193ef1dd4 100644 --- a/crates/compilers/src/compile/output/mod.rs +++ b/crates/compilers/src/compile/output/mod.rs @@ -872,7 +872,7 @@ impl AggregatedCompilerOutput { self.contracts.contracts_with_files().filter(|(path, _, _)| *path == contract_path).any( |(_, _, contract)| { - contract.abi.as_ref().map_or(false, |abi| abi.functions.contains_key("IS_TEST")) + contract.abi.as_ref().is_some_and(|abi| abi.functions.contains_key("IS_TEST")) }, ) } diff --git a/crates/compilers/src/compilers/solc/mod.rs b/crates/compilers/src/compilers/solc/mod.rs index d3aebcd6f..218d51cc9 100644 --- a/crates/compilers/src/compilers/solc/mod.rs +++ b/crates/compilers/src/compilers/solc/mod.rs @@ -201,8 +201,8 @@ impl Restriction { /// /// If given None, only returns true if no restrictions are set pub fn satisfies(&self, value: Option) -> bool { - self.min.map_or(true, |min| value.map_or(false, |v| v >= min)) - && self.max.map_or(true, |max| value.map_or(false, |v| v <= max)) + self.min.is_none_or(|min| value.is_some_and(|v| v >= min)) + && self.max.is_none_or(|max| value.is_some_and(|v| v <= max)) } /// Combines two restrictions into a new one @@ -346,7 +346,7 @@ impl CompilerSettings for SolcSettings { // Ensure that we either don't have min optimizer runs set or that the optimizer is enabled satisfies &= optimizer_runs .min - .map_or(true, |min| min == 0 || self.optimizer.enabled.unwrap_or_default()); + .is_none_or(|min| min == 0 || self.optimizer.enabled.unwrap_or_default()); satisfies } diff --git a/crates/compilers/src/filter.rs b/crates/compilers/src/filter.rs index 9038e50c6..119d96744 100644 --- a/crates/compilers/src/filter.rs +++ b/crates/compilers/src/filter.rs @@ -142,7 +142,7 @@ impl<'a> SparseOutputFilter<'a> { .collect(); // Remove clean sources, those will be read from cache. - full_compilation.retain(|file| sources.0.get(file).map_or(false, |s| s.is_dirty())); + full_compilation.retain(|file| sources.0.get(file).is_some_and(|s| s.is_dirty())); settings.update_output_selection(|selection| { trace!( diff --git a/crates/compilers/src/lib.rs b/crates/compilers/src/lib.rs index 26f1c085e..d273cbe8c 100644 --- a/crates/compilers/src/lib.rs +++ b/crates/compilers/src/lib.rs @@ -403,7 +403,7 @@ impl Project { { let mut contracts = self.collect_contract_names()?; - if contracts.get(target_name).map_or(true, |paths| paths.is_empty()) { + if contracts.get(target_name).is_none_or(|paths| paths.is_empty()) { return Err(SolcError::msg(format!("No contract found with the name `{target_name}`"))); } let mut paths = contracts.remove(target_name).unwrap(); diff --git a/crates/compilers/src/resolver/parse.rs b/crates/compilers/src/resolver/parse.rs index d4e270908..adaf96d3a 100644 --- a/crates/compilers/src/resolver/parse.rs +++ b/crates/compilers/src/resolver/parse.rs @@ -45,7 +45,7 @@ impl SolData { /// This will attempt to parse the solidity AST and extract the imports and version pragma. If /// parsing fails, we'll fall back to extract that info via regex pub fn parse(content: &str, file: &Path) -> Self { - let is_yul = file.extension().map_or(false, |ext| ext == "yul"); + let is_yul = file.extension().is_some_and(|ext| ext == "yul"); let mut version = None; let mut experimental = None; let mut imports = Vec::>::new();