Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cryptic type error for multiple return values #164

Closed
nmushegian opened this issue Oct 21, 2015 · 12 comments
Closed

cryptic type error for multiple return values #164

nmushegian opened this issue Oct 21, 2015 · 12 comments

Comments

@nmushegian
Copy link

@nmushegian nmushegian commented Oct 21, 2015

contract MultiReturner {
    function get() returns (bytes value, bool ok) {
        bytes memory val;
        return (val, true);
    }
}

contract MultiRetUser {
    function try_to_get() {
        var mr = new MultiReturner();
        bytes memory value;
        bool ok;
        (value, ok) = mr.get();
    }
}
lang/multiret_test.sol:14:23: Error: Type bool is not implicitly convertible to expected type tuple(bytes memory,bool).
        (value, ok) = mr.get();
                      ^

same error if I switch the order. No error if I use bytes32 instead of bytes.

@chriseth
Copy link
Contributor

@chriseth chriseth commented Oct 21, 2015

@chriseth chriseth closed this Oct 21, 2015
@chriseth
Copy link
Contributor

@chriseth chriseth commented Oct 21, 2015

I just realised that I should probably explain why this happens:
The EVM is unable to read variably-sized data from external function calls. Because of that, such types are removed from the signature of functions.
Note that on the other hand, it is possible to return variably-sized data, it just cannot be read from within the EVM.

@nmushegian
Copy link
Author

@nmushegian nmushegian commented Oct 22, 2015

I don't understand how this can be an EVM restriction, if it can read fixed-size data of arbitrary size when you know the type.

@nmushegian
Copy link
Author

@nmushegian nmushegian commented Oct 22, 2015

The only explanation I can think of is that the evm requires you to say the size of the calldata buffer for the return value when you are making the call. What happens if you just say that it has size 2^256, then parse the return value lengths yourself?

@Nashatyrev
Copy link
Member

@Nashatyrev Nashatyrev commented Oct 22, 2015

Chris,
can you please elaborate more on this?
Does it mean that absolutely no EVM contracts (Solidity or others) can read returned dynamic type values from internal calls?
Thanks!

@chriseth
Copy link
Contributor

@chriseth chriseth commented Oct 22, 2015

Before making the call, you have to specify the location where the return value should be put (position and length). The problem is that you already have to pay for memory usage before you make the call, so just specifying 2**256 for the length will use up all your gas.

These restrictions are not specific to Solidity.

@nmushegian
Copy link
Author

@nmushegian nmushegian commented Oct 22, 2015

This is another argument for supporting a feature like
low_level_call( bytes calldata, uint buffer_size ) returns (bytes data, bool ok)
you can detect whether your dynamically-sized type is readable or not

@nmushegian
Copy link
Author

@nmushegian nmushegian commented Oct 22, 2015

#14

@Nashatyrev
Copy link
Member

@Nashatyrev Nashatyrev commented Oct 22, 2015

So if there is a contract returning int[] I can use it only via ABI but have no chances to call it from another contract. Quite sad limitation.

@chriseth
Copy link
Contributor

@chriseth chriseth commented Oct 22, 2015

@nmushegian low_level_call will not help here - because even with a low level call there is no way to reserve space in memory whose size depends on a value that is only computed in the function that is called.

@Nashatyrev you are right. We plan to remove this limitation in Ethereum 2.0.

@nmushegian
Copy link
Author

@nmushegian nmushegian commented Oct 22, 2015

What I meant was that I specify the size in the caller. I'm that if the callee tries to write too much to the return data, it just truncates it or crashes the transaction. So the caller should be able to interpret it as a dynamic array if I insist, if the array size is in the first word then I can check if it was too big and know that it failed. Then in the callee I just return (bytes, bool) and don't worry about the size.

@raineorshine
Copy link
Contributor

@raineorshine raineorshine commented Aug 5, 2016

Would it be possible to just get a better error message in the mean time? This seems like a common gotcha.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants
You can’t perform that action at this time.