Skip to content

Commit 4065d38

Browse files
authored
fix(chisel): final statement & fetch err with complex type fixes (#9081)
* fix(chisel): consider assembly block return as final statement * Fix 4938 * Start from first assembly block when checking for return statement * Fix 6618
1 parent f79c53c commit 4065d38

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed

crates/chisel/src/dispatcher.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
},
1111
session_source::SessionSource,
1212
};
13-
use alloy_json_abi::JsonAbi;
13+
use alloy_json_abi::{InternalType, JsonAbi};
1414
use alloy_primitives::{hex, Address};
1515
use forge_fmt::FormatterConfig;
1616
use foundry_config::{Config, RpcEndpoint};
@@ -528,7 +528,22 @@ impl ChiselDispatcher {
528528
err.name,
529529
err.inputs
530530
.iter()
531-
.map(|input| format_param!(input))
531+
.map(|input| {
532+
let mut param_type = &input.ty;
533+
// If complex type then add the name of custom type.
534+
// see <https://github.com/foundry-rs/foundry/issues/6618>.
535+
if input.is_complex_type() {
536+
if let Some(
537+
InternalType::Enum { contract: _, ty } |
538+
InternalType::Struct { contract: _, ty } |
539+
InternalType::Other { contract: _, ty },
540+
) = &input.internal_type
541+
{
542+
param_type = ty;
543+
}
544+
}
545+
format!("{} {}", param_type, input.name)
546+
})
532547
.collect::<Vec<_>>()
533548
.join(",")
534549
));

crates/chisel/src/executor.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@ impl SessionSource {
4949
// Fetch the run function's body statement
5050
let run_func_statements = compiled.intermediate.run_func_body()?;
5151

52+
// Record loc of first yul block return statement (if any).
53+
// This is used to decide which is the final statement within the `run()` method.
54+
// see <https://github.com/foundry-rs/foundry/issues/4617>.
55+
let last_yul_return = run_func_statements.iter().find_map(|statement| {
56+
if let pt::Statement::Assembly { loc: _, dialect: _, flags: _, block } = statement {
57+
if let Some(statement) = block.statements.last() {
58+
if let pt::YulStatement::FunctionCall(yul_call) = statement {
59+
if yul_call.id.name == "return" {
60+
return Some(statement.loc())
61+
}
62+
}
63+
}
64+
}
65+
None
66+
});
67+
5268
// Find the last statement within the "run()" method and get the program
5369
// counter via the source map.
5470
if let Some(final_statement) = run_func_statements.last() {
@@ -58,9 +74,13 @@ impl SessionSource {
5874
//
5975
// There is some code duplication within the arms due to the difference between
6076
// the [pt::Statement] type and the [pt::YulStatement] types.
61-
let source_loc = match final_statement {
77+
let mut source_loc = match final_statement {
6278
pt::Statement::Assembly { loc: _, dialect: _, flags: _, block } => {
63-
if let Some(statement) = block.statements.last() {
79+
// Select last non variable declaration statement, see <https://github.com/foundry-rs/foundry/issues/4938>.
80+
let last_statement = block.statements.iter().rev().find(|statement| {
81+
!matches!(statement, pt::YulStatement::VariableDeclaration(_, _, _))
82+
});
83+
if let Some(statement) = last_statement {
6484
statement.loc()
6585
} else {
6686
// In the case where the block is empty, attempt to grab the statement
@@ -88,6 +108,13 @@ impl SessionSource {
88108
_ => final_statement.loc(),
89109
};
90110

111+
// Consider yul return statement as final statement (if it's loc is lower) .
112+
if let Some(yul_return) = last_yul_return {
113+
if yul_return.end() < source_loc.start() {
114+
source_loc = yul_return;
115+
}
116+
}
117+
91118
// Map the source location of the final statement of the `run()` function to its
92119
// corresponding runtime program counter
93120
let final_pc = {

0 commit comments

Comments
 (0)