hyperledger-solang / solang

Solidity Compiler for Solana and Polkadot
https://solang.readthedocs.io/
Apache License 2.0
1.26k stars 210 forks source link

Solang-parser: `Try` statements parse inconsistently #1661

Open brockelmore opened 1 month ago

brockelmore commented 1 month ago

Describe the bug

Consider the following cases:

  1. The function called with try has a return value:
    
    contract A {
    function try_catch_func_require() public view returns (uint) {
        try T(address(1)).t() returns (uint) {
            return 2;
        } catch Error(string memory reason) {
            return 1;
        }
    }
    }

contract T { function t() public view returns (uint) {} }

2. The function called with `try` does *not* have a return value:
```solidity
contract A {
    function try_catch_func_require() public view returns (uint) {
        try T(address(1)).t() {
            return 2;
        } catch Error(string memory reason) {
            return 1;
        }
    }
}

contract T {
    function t() public view  {}
}

In case 1, the Try statement looks like the following:

fn print_try(t: Statement) {
    let Statement::Try(loc, func_expr, maybe_return, maybe_catches) = t else { unreachable!()};
    println!("{func_expr}");
}

it looks like the following:

T(address(1)).t(0, 101)

It is just the function call (this makes sense!)

In case 2 (without a function return specified), it looks like the following:

T(address(1)).t(0, 101){return 2;}

i.e. it is a FunctionCallBlock

Additionally this actually seems truly unintended per the docs:

Try(Loc, Expression, Option<(ParameterList, Box<Statement>)>, Vec<CatchClause>)

try <1> [returns (<2.1>,*) <2.2>] <3>*

<1> is either New(FunctionCall) or FunctionCall.

edit: I may have misunderstood the docs, and it may be that it can be a lalrpop FunctionCall not an Expression::FunctionCall, which would make sense because it could be named args function call. Still, its a bit weird to have to special case try blocks that have a function return vs those that dont

To Reproduce Steps to reproduce the behavior: See above

Expected behavior Try's first expression should always either be New(FunctionCall) or FunctionCall.

Hyperledger Solang version Solang-parser v0.3.3