diff --git a/Cargo.lock b/Cargo.lock index 50ba6db093cbd..5dc165892675a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4512,9 +4512,9 @@ dependencies = [ [[package]] name = "foundry-compilers" -version = "0.19.3" +version = "0.19.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fdd6b9a368a06cecafec694c9ff0cd1f960bc896d9575d9b8397ec46d6c6235" +checksum = "5767bfd01a240b57e6eb540e233b248d2ecb554d60b7936574cd077c0bd4c15e" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -4544,9 +4544,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts" -version = "0.19.3" +version = "0.19.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9260e059261a97b19d1fa14eb56ae97d99733a58b4453263dab383ecd680fa86" +checksum = "2b35da40bb333baff6f4533431c050a94857a4d1a379365085da403938fc9edf" dependencies = [ "foundry-compilers-artifacts-solc", "foundry-compilers-artifacts-vyper", @@ -4554,9 +4554,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-solc" -version = "0.19.3" +version = "0.19.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92405587ef0dfebcf4f672c04756e28dafa44691b68eddfd828577d7fff04314" +checksum = "eff50fa9f518e96f80c77d1596122bb41c6fb9f1ec8d93e3127e2cf7a4726faa" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -4575,9 +4575,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-vyper" -version = "0.19.3" +version = "0.19.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3258aaf0cdfab7a2736652c9ffcbbcd06ec97433c51b1baf5160fde2e5dd4d9d" +checksum = "34764d842fcf3aee77dc892beba3f12d7d5cebe196caf2050302caa986de8914" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -4590,9 +4590,9 @@ dependencies = [ [[package]] name = "foundry-compilers-core" -version = "0.19.3" +version = "0.19.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bfc4e31d14c92aee7661ef25418941ce80fab13b97e0e2bc09ddfaa8027b601" +checksum = "48bcd9ff6881e2f5acd8544d490cc91d2c1d47c59c1e9337ea2ade66ce7e1800" dependencies = [ "alloy-primitives", "cfg-if", @@ -5509,7 +5509,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.0", + "socket2 0.5.10", "system-configuration", "tokio", "tower-service", @@ -5763,7 +5763,7 @@ checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "arbitrary", "equivalent", - "hashbrown 0.16.0", + "hashbrown 0.15.5", "serde", "serde_core", ] @@ -7686,7 +7686,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.0", + "socket2 0.5.10", "thiserror 2.0.16", "tokio", "tracing", @@ -7723,7 +7723,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.0", + "socket2 0.5.10", "tracing", "windows-sys 0.60.2", ] @@ -9140,9 +9140,9 @@ dependencies = [ [[package]] name = "solar-ast" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bacae15e3ff9a01747580d0ee9816ff6a51fa26f190cdc51b46263d555f7333b" +checksum = "9b6aaf98d032ba3be85dca5f969895ade113a9137bb5956f80c5faf14689de59" dependencies = [ "alloy-primitives", "bumpalo", @@ -9157,9 +9157,9 @@ dependencies = [ [[package]] name = "solar-compiler" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf8d32cb292fcb5aab4158bd3215f7e3515424acfe780e54283bd520abf395a" +checksum = "95e792060bcbb007a6b9b060292945fb34ff854c7d93a9628f81b6c809eb4360" dependencies = [ "alloy-primitives", "solar-ast", @@ -9173,9 +9173,9 @@ dependencies = [ [[package]] name = "solar-config" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f0368370d4e7bc45586dfa545867f6685c1d8ec46a29843031f0563c88e4ff" +checksum = "ff16d692734c757edd339f5db142ba91b42772f8cbe1db1ce3c747f1e777185f" dependencies = [ "colorchoice", "strum 0.27.2", @@ -9183,9 +9183,9 @@ dependencies = [ [[package]] name = "solar-data-structures" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e246a9af3cc34b40e7612b600a5495f70768bdd365f9fa338d64afb33a59a96b" +checksum = "2dea34e58332c7d6a8cde1f1740186d31682b7be46e098b8cc16fcb7ffd98bf5" dependencies = [ "bumpalo", "index_vec", @@ -9198,9 +9198,9 @@ dependencies = [ [[package]] name = "solar-interface" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e2e4dec38bc1940946f8d303260920f57022dc5a558a3786c3b83e121c23c6" +checksum = "2d6163af2e773f4d455212fa9ba2c0664506029dd26232eb406f5046092ac311" dependencies = [ "annotate-snippets 0.12.4", "anstream", @@ -9219,16 +9219,16 @@ dependencies = [ "solar-config", "solar-data-structures", "solar-macros", - "thiserror 2.0.16", + "thiserror 1.0.69", "tracing", "unicode-width 0.2.0", ] [[package]] name = "solar-macros" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b3d7b35daa205064e7965584b3144b73b38acce2257c21d01e351b8f8812d7" +checksum = "44a98045888d75d17f52e7b76f6098844b76078b5742a450c3ebcdbdb02da124" dependencies = [ "proc-macro2", "quote", @@ -9237,9 +9237,9 @@ dependencies = [ [[package]] name = "solar-parse" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54766e7b5696cdfad50c0ea325035dd106ed2377635f1eb45db3043b6d117373" +checksum = "19b77a9cbb07948e4586cdcf64f0a483424197308816ebd57a4cf06130b68562" dependencies = [ "alloy-primitives", "bitflags 2.9.4", @@ -9259,9 +9259,9 @@ dependencies = [ [[package]] name = "solar-sema" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "979354fd20a7ee6229d66d49a3c3ca1e37be0e780b5b6aa864109c327142b529" +checksum = "cd033af43a38da316a04b25bbd20b121ce5d728b61e6988fd8fd6e2f1e68d0a1" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -9560,7 +9560,7 @@ dependencies = [ "serde_json", "sha2 0.10.9", "tempfile", - "thiserror 2.0.16", + "thiserror 1.0.69", "url", "zip", ] diff --git a/Cargo.toml b/Cargo.toml index fa25d24f3a694..69bc196e77798 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -209,13 +209,13 @@ foundry-linking = { path = "crates/linking" } # solc & compilation utilities foundry-block-explorers = { version = "0.22.0", default-features = false } -foundry-compilers = { version = "0.19.1", default-features = false, features = [ +foundry-compilers = { version = "0.19.5", default-features = false, features = [ "rustls", "svm-solc", ] } foundry-fork-db = "0.18" solang-parser = { version = "=0.3.9", package = "foundry-solang-parser" } -solar = { package = "solar-compiler", version = "=0.1.7", default-features = false } +solar = { package = "solar-compiler", version = "=0.1.8", default-features = false } svm = { package = "svm-rs", version = "0.5", default-features = false, features = [ "rustls", ] } @@ -427,7 +427,7 @@ rexpect = { git = "https://github.com/rust-cli/rexpect", rev = "2ed0b1898d7edaf6 ## foundry # foundry-block-explorers = { git = "https://github.com/foundry-rs/block-explorers.git", rev = "f5b46b2" } -# foundry-compilers = { git = "https://github.com/foundry-rs/compilers.git", branch = "dani/bump-solar" } +# foundry-compilers = { git = "https://github.com/foundry-rs/compilers.git", branch = "main" } # foundry-fork-db = { git = "https://github.com/foundry-rs/foundry-fork-db", rev = "eee6563" } # solar diff --git a/crates/evm/coverage/src/analysis.rs b/crates/evm/coverage/src/analysis.rs index f226457b18fef..795e9a177d272 100644 --- a/crates/evm/coverage/src/analysis.rs +++ b/crates/evm/coverage/src/analysis.rs @@ -367,7 +367,7 @@ impl<'ast> ast::Visit<'ast> for SourceVisitor<'_> { stmt.span, ); } - StmtKind::For { body, .. } => { + StmtKind::For(yul::StmtFor { body, .. }) => { self.push_stmt(body.span); } StmtKind::Switch(switch) => { diff --git a/crates/fmt/src/state/common.rs b/crates/fmt/src/state/common.rs index d21725dda30f2..15d8c32c224f8 100644 --- a/crates/fmt/src/state/common.rs +++ b/crates/fmt/src/state/common.rs @@ -212,7 +212,7 @@ impl<'ast> State<'_, 'ast> { format: ListFormat, ) where P: FnMut(&mut Self, &'a T), - S: FnMut(&T) -> Option + Copy, + S: FnMut(&T) -> Span, { if self.handle_span(Span::new(pos_lo, pos_hi), true) { return; @@ -232,26 +232,24 @@ impl<'ast> State<'_, 'ast> { } // Format single-item inline lists directly without boxes - self.print_inside_parens(|state| match get_span(&values[0]) { - Some(span) => { - state.s.cbox(state.ind); - let mut skip_break = true; - if state.peek_comment_before(span.hi()).is_some() { - state.hardbreak(); - skip_break = false; - } + self.print_inside_parens(|state| { + let span = get_span(&values[0]); + state.s.cbox(state.ind); + let mut skip_break = true; + if state.peek_comment_before(span.hi()).is_some() { + state.hardbreak(); + skip_break = false; + } - state.print_comments(span.lo(), CommentConfig::skip_ws().mixed_prev_space()); - print(state, &values[0]); + state.print_comments(span.lo(), CommentConfig::skip_ws().mixed_prev_space()); + print(state, &values[0]); - if !state.print_trailing_comment(span.hi(), None) && skip_break { - state.neverbreak(); - } else { - state.break_offset_if_not_bol(0, -state.ind, false); - } - state.end(); + if !state.print_trailing_comment(span.hi(), None) && skip_break { + state.neverbreak(); + } else { + state.break_offset_if_not_bol(0, -state.ind, false); } - None => print(state, &values[0]), + state.end(); }); } @@ -263,7 +261,7 @@ impl<'ast> State<'_, 'ast> { get_span: S, ) where P: FnMut(&mut Self, &'a T), - S: FnMut(&T) -> Option, + S: FnMut(&T) -> Span, { if self.handle_span(span, false) { return; @@ -281,9 +279,9 @@ impl<'ast> State<'_, 'ast> { format: ListFormat, ) -> bool where - S: FnMut(&T) -> Option, + S: FnMut(&T) -> Span, { - let Some(span) = values.first().and_then(&mut get_span) else { + let Some(span) = values.first().map(&mut get_span) else { return false; }; @@ -357,7 +355,7 @@ impl<'ast> State<'_, 'ast> { format: ListFormat, ) where P: FnMut(&mut Self, &'a T), - S: FnMut(&T) -> Option, + S: FnMut(&T) -> Span, { if values.is_empty() { return; @@ -366,8 +364,8 @@ impl<'ast> State<'_, 'ast> { let first = get_span(&values[0]); // we can't simply check `peek_comment_before(pos_hi)` cause we would also account for // comments in the child expression, and those don't matter. - let has_comments = self.peek_comment_before(first.map_or(pos_hi, |s| s.lo())).is_some() - || self.peek_comment_between(first.map_or(pos_hi, |s| s.hi()), pos_hi).is_some(); + let has_comments = self.peek_comment_before(first.lo()).is_some() + || self.peek_comment_between(first.hi(), pos_hi).is_some(); let is_single_without_cmnts = values.len() == 1 && !format.break_single && !has_comments; let skip_first_break = if format.with_delimiters || format.is_inline() { @@ -399,10 +397,9 @@ impl<'ast> State<'_, 'ast> { is_single_without_cmnts || !format.with_delimiters || format.is_inline(); for (i, value) in values.iter().enumerate() { let is_last = i == values.len() - 1; - if let Some(span) = get_span(value) - && self - .print_comments(span.lo(), CommentConfig::skip_ws().mixed_prev_space()) - .is_some_and(|cmnt| cmnt.is_mixed()) + if self + .print_comments(get_span(value).lo(), CommentConfig::skip_ws().mixed_prev_space()) + .is_some_and(|cmnt| cmnt.is_mixed()) && format.breaks_cmnts { self.hardbreak(); // trailing and isolated comments already hardbreak @@ -414,7 +411,7 @@ impl<'ast> State<'_, 'ast> { self.print_word(","); } - let next_span = if is_last { None } else { get_span(&values[i + 1]) }; + let next_span = if is_last { None } else { Some(get_span(&values[i + 1])) }; let next_pos = next_span.map(Span::lo).unwrap_or(pos_hi); if !is_last @@ -447,7 +444,12 @@ impl<'ast> State<'_, 'ast> { && !self.is_bol_or_only_ind() && !self.inline_config.is_disabled(next_span) { - format.print_break(false, values.len(), &mut self.s); + if next_span.is_dummy() && !matches!(format.kind, ListFormatKind::AlwaysBreak) { + // Don't add spaces between uninformed items (commas) + self.zerobreak(); + } else { + format.print_break(false, values.len(), &mut self.s); + } } } diff --git a/crates/fmt/src/state/mod.rs b/crates/fmt/src/state/mod.rs index 86cccb1552c1a..437f634b2e24f 100644 --- a/crates/fmt/src/state/mod.rs +++ b/crates/fmt/src/state/mod.rs @@ -702,7 +702,9 @@ impl<'sess> State<'sess, '_> { } CommentStyle::Isolated => { let Some(mut prefix) = cmnt.prefix() else { return }; - config.hardbreak_if_not_bol(self.is_bol_or_only_ind(), &mut self.s); + if !config.iso_no_break { + config.hardbreak_if_not_bol(self.is_bol_or_only_ind(), &mut self.s); + } if self.config.wrap_comments { // Merge and wrap comments diff --git a/crates/fmt/src/state/sol.rs b/crates/fmt/src/state/sol.rs index 65b4b13b90dbc..cd5fc09ade178 100644 --- a/crates/fmt/src/state/sol.rs +++ b/crates/fmt/src/state/sol.rs @@ -10,16 +10,20 @@ use crate::{ }; use foundry_common::{comments::Comment, iter::IterDelimited}; use foundry_config::fmt::{self as config, MultilineFuncHeaderStyle}; -use solar::parse::{ - ast::{self, Span}, - interface::BytePos, +use solar::{ + ast::BoxSlice, + interface::SpannedOption, + parse::{ + ast::{self, Span}, + interface::BytePos, + }, }; use std::{collections::HashMap, fmt::Debug}; #[rustfmt::skip] macro_rules! get_span { - () => { |value| Some(value.span) }; - (()) => { |value| Some(value.span()) }; + () => { |value| value.span }; + (()) => { |value| value.span() }; } /// Language-specific pretty printing: Solidity. @@ -686,7 +690,10 @@ impl<'ast> State<'_, 'ast> { // 1. exactly matches the name of a base contract as declared in the `contract is`; // this does not account for inheritance; let is_contract_base = self.contract.is_some_and(|contract| { - contract.bases.iter().any(|contract_base| contract_base.name == modifier.name) + contract + .bases + .iter() + .any(|contract_base| contract_base.name.to_string() == modifier.name.to_string()) }); // 2. assume that title case names in constructors are bases. // LEGACY: constructors used to also be `function NameOfContract...`; not checked. @@ -1216,12 +1223,17 @@ impl<'ast> State<'_, 'ast> { exprs, span.lo(), span.hi(), - |this, expr| { - if let Some(expr) = expr { - this.print_expr(expr); + |this, expr| match expr.as_ref() { + SpannedOption::Some(expr) => this.print_expr(expr), + SpannedOption::None(span) => { + this.print_comments(span.hi(), CommentConfig::skip_ws().no_breaks()); } }, - |e| e.as_deref().map(|e| e.span), + |expr| match expr.as_ref() { + SpannedOption::Some(expr) => expr.span, + // Manually handled by printing the comment when `None` + SpannedOption::None(..) => Span::DUMMY, + }, ListFormat::compact().break_single(is_binary_expr(&expr.kind)), ), ast::ExprKind::TypeCall(ty) => { @@ -1669,7 +1681,7 @@ impl<'ast> State<'_, 'ast> { s.print_expr(arg.value); s.end(); }, - |arg| Some(arg.name.span.until(arg.value.span)), + |arg| arg.name.span.until(arg.value.span), list_format.break_cmnts().break_single(true).without_ind(self.call_stack.is_chain()), ); self.word("}"); @@ -1797,7 +1809,7 @@ impl<'ast> State<'_, 'ast> { fn print_multi_decl_stmt( &mut self, span: Span, - vars: &'ast [Option>], + vars: &'ast BoxSlice<'ast, SpannedOption>>, init_expr: &'ast ast::Expr<'ast>, ) { let space_left = self.space_left(); @@ -1808,24 +1820,26 @@ impl<'ast> State<'_, 'ast> { vars, span.lo(), init_expr.span.lo(), - |this, var| { - // NOTE(rusowsky): unless we add more spans to solar, it is not possible to print - // comments between the commas of unhandled vars - if let Some(var) = var { - this.print_var(var, true); + |this, var| match var { + SpannedOption::Some(var) => this.print_var(var, true), + SpannedOption::None(span) => { + this.print_comments(span.hi(), CommentConfig::skip_ws().no_breaks()); } }, - |v| v.as_ref().map(|v| v.span), + |var| match var { + SpannedOption::Some(var) => var.span, + // Manually handled by printing the comment when `None` + SpannedOption::None(..) => Span::DUMMY, + }, ListFormat::consistent(), ); self.end(); self.word(" ="); // '(' + var + ', ' + var + ')' + ' =' - let vars_size = vars - .iter() - .fold(0, |acc, v| acc + v.as_ref().map_or(0, |v| self.estimate_size(v.span)) + 2) - + 2; + let vars_size = vars.iter().fold(0, |acc, var| { + acc + var.as_ref().unspan().map_or(0, |v| self.estimate_size(v.span)) + 2 + }) + 2; self.call_stack.add_precall(vars_size); if self.estimate_size(init_expr.span) + self.config.tab_width diff --git a/crates/fmt/src/state/yul.rs b/crates/fmt/src/state/yul.rs index eb475c5c05240..6386e34089c0a 100644 --- a/crates/fmt/src/state/yul.rs +++ b/crates/fmt/src/state/yul.rs @@ -8,8 +8,8 @@ use solar::parse::ast::{self, Span, yul}; #[rustfmt::skip] macro_rules! get_span { - () => { |value| Some(value.span) }; - (()) => { |value| Some(value.span()) }; + () => { |value| value.span }; + (()) => { |value| value.span() }; } /// Language-specific pretty printing: Yul. @@ -43,18 +43,18 @@ impl<'ast> State<'_, 'ast> { self.space(); self.s.offset(self.ind); self.ibox(0); - self.print_yul_expr_call(expr_call, span); + self.print_yul_expr(expr_call); self.end(); self.end(); } - yul::StmtKind::Expr(expr_call) => self.print_yul_expr_call(expr_call, span), + yul::StmtKind::Expr(expr_call) => self.print_yul_expr(expr_call), yul::StmtKind::If(expr, stmts) => { self.word("if "); self.print_yul_expr(expr); self.nbsp(); self.print_yul_block(stmts, span, false); } - yul::StmtKind::For { init, cond, step, body } => { + yul::StmtKind::For(yul::StmtFor { init, cond, step, body }) => { self.ibox(0); self.word("for "); @@ -171,7 +171,17 @@ impl<'ast> State<'_, 'ast> { match kind { yul::ExprKind::Path(path) => self.print_path(path, false), - yul::ExprKind::Call(call) => self.print_yul_expr_call(call, span), + yul::ExprKind::Call(yul::ExprCall { name, arguments }) => { + self.print_ident(name); + self.print_tuple( + arguments, + span.lo(), + span.hi(), + |s, arg| s.print_yul_expr(arg), + get_span!(), + ListFormat::consistent().break_single(true), + ); + } yul::ExprKind::Lit(lit) => { if matches!(&lit.kind, ast::LitKind::Address(_)) { self.print_span_cold(lit.span); @@ -182,19 +192,6 @@ impl<'ast> State<'_, 'ast> { } } - fn print_yul_expr_call(&mut self, expr: &'ast yul::ExprCall<'ast>, span: Span) { - let yul::ExprCall { name, arguments } = expr; - self.print_ident(name); - self.print_tuple( - arguments, - span.lo(), - span.hi(), - |s, arg| s.print_yul_expr(arg), - get_span!(), - ListFormat::consistent().break_single(true), - ); - } - pub(super) fn print_yul_block( &mut self, block: &'ast yul::Block<'ast>, diff --git a/crates/fmt/testdata/SimpleComments/fmt.sol b/crates/fmt/testdata/SimpleComments/fmt.sol index 6e8d5195bd143..54f2e56dabbc4 100644 --- a/crates/fmt/testdata/SimpleComments/fmt.sol +++ b/crates/fmt/testdata/SimpleComments/fmt.sol @@ -49,6 +49,22 @@ contract SimpleComments { return // a line comment that exceeds line width value; } + + // https://github.com/foundry-rs/foundry/issues/11836 + function test5() public { + ( + /* poolIndex */, + uint256 sellAmount1, + uint256 buyAmount1, + /* poolKey1 */, + /* sellToken */, + /* buyToken */, + /* sellTokenBalanceBefore */, + uint256 buyTokenBalanceBefore1, + /* hashMul */, + /* hashMod */ + ) = _swapPre(2, TOTAL_SUPPLY / 1_000, false, zeroForOne1); + } } /* diff --git a/crates/fmt/testdata/SimpleComments/original.sol b/crates/fmt/testdata/SimpleComments/original.sol index d41c686b2f783..b2c895d05660c 100644 --- a/crates/fmt/testdata/SimpleComments/original.sol +++ b/crates/fmt/testdata/SimpleComments/original.sol @@ -50,6 +50,22 @@ contract SimpleComments { return // a line comment that exceeds line width value; } + + // https://github.com/foundry-rs/foundry/issues/11836 + function test5() public { + ( + /* poolIndex */, + uint256 sellAmount1, + uint256 buyAmount1, + /* poolKey1 */, + /* sellToken */, + /* buyToken */, + /* sellTokenBalanceBefore */, + uint256 buyTokenBalanceBefore1, + /* hashMul */, + /* hashMod */ + ) = _swapPre(2, TOTAL_SUPPLY / 1_000, false, zeroForOne1); + } } /* @@ -80,4 +96,4 @@ function test() {} // some comment // another comment -// eof comment \ No newline at end of file +// eof comment diff --git a/crates/fmt/testdata/SimpleComments/wrap-comments.fmt.sol b/crates/fmt/testdata/SimpleComments/wrap-comments.fmt.sol index 7bc1e8249340c..d2a340bb2f7b9 100644 --- a/crates/fmt/testdata/SimpleComments/wrap-comments.fmt.sol +++ b/crates/fmt/testdata/SimpleComments/wrap-comments.fmt.sol @@ -60,6 +60,24 @@ contract SimpleComments { return // a line comment that exceeds line width value; } + + // https://github.com/foundry-rs/foundry/issues/11836 + function test5() public { + ( + /* poolIndex */, + uint256 sellAmount1, + uint256 buyAmount1, + /* poolKey1 */, + /* sellToken */, + /* buyToken */, + /* sellTokenBalanceBefore */, + uint256 buyTokenBalanceBefore1, + /* hashMul */, + /* hashMod */ + ) = _swapPre( + 2, TOTAL_SUPPLY / 1_000, false, zeroForOne1 + ); + } } /* diff --git a/crates/lint/src/sol/med/div_mul.rs b/crates/lint/src/sol/med/div_mul.rs index 6640a1ea1f9f8..a9be610d6e4c3 100644 --- a/crates/lint/src/sol/med/div_mul.rs +++ b/crates/lint/src/sol/med/div_mul.rs @@ -3,7 +3,10 @@ use crate::{ linter::{EarlyLintPass, LintContext}, sol::{Severity, SolLint}, }; -use solar::ast::{BinOp, BinOpKind, Expr, ExprKind}; +use solar::{ + ast::{BinOp, BinOpKind, Expr, ExprKind}, + interface::SpannedOption, +}; declare_forge_lint!( DIVIDE_BEFORE_MULTIPLY, @@ -26,7 +29,11 @@ fn contains_division<'ast>(expr: &'ast Expr<'ast>) -> bool { match &expr.kind { ExprKind::Binary(_, BinOp { kind: BinOpKind::Div, .. }, _) => true, ExprKind::Tuple(inner_exprs) => inner_exprs.iter().any(|opt_expr| { - if let Some(inner_expr) = opt_expr { contains_division(inner_expr) } else { false } + if let SpannedOption::Some(inner_expr) = opt_expr.as_ref() { + contains_division(inner_expr) + } else { + false + } }), _ => false, }