Merge pull request #13227 from ethereum/functions_taking_calldata_args_should_be_assignable_to_function_pointer_of_same_type

functions taking calldata args should be assignable to function pointers of same type
This commit is contained in:
Kamil Śliwak 2022-10-26 14:35:24 +02:00 committed by GitHub
commit 05c457181e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 54 additions and 0 deletions

View File

@ -789,6 +789,18 @@ This includes private, internal and public functions of both contracts and libra
functions.
External function types, on the other hand, are only compatible with public and external contract
functions.
.. note::
External functions with ``calldata`` parameters are incompatible with external function types with ``calldata`` parameters.
They are compatible with the corresponding types with ``memory`` parameters instead.
For example, there is no function that can be pointed at by a value of type ``function (string calldata) external`` while
``function (string memory) external`` can point at both ``function f(string memory) external {}`` and
``function g(string calldata) external {}``.
This is because for both locations the arguments are passed to the function in the same way.
The caller cannot pass its calldata directly to an external function and always ABI-encodes the arguments into memory.
Marking the parameters as ``calldata`` only affects the implementation of the external function and is
meaningless in a function pointer on the caller's side.
Libraries are excluded because they require a ``delegatecall`` and use :ref:`a different ABI
convention for their selectors <library-selectors>`.
Functions declared in interfaces do not have definitions so pointing at them does not make sense either.

View File

@ -0,0 +1,10 @@
contract C {
function g(string calldata) external returns (bool) { return true; }
function main() external returns (bool) {
function (string memory) external returns (bool) ptr = this.g;
return ptr("testString");
}
}
// ----
// main() -> true

View File

@ -0,0 +1,14 @@
contract C {
function f(function (string calldata) external) external {}
function g(string calldata) external {}
function main() external {
function (string calldata) external ptr = this.g;
abi.encodeCall(this.f, (this.g));
this.f(this.g);
}
}
// ----
// TypeError 9574: (161-209): Type function (string memory) external is not implicitly convertible to expected type function (string calldata) external.
// TypeError 5407: (242-250): Cannot implicitly convert component at position 0 from "function (string memory) external" to "function (string calldata) external".
// TypeError 9553: (268-274): Invalid type for argument in function call. Invalid implicit conversion from function (string memory) external to function (string calldata) external requested.

View File

@ -0,0 +1,9 @@
contract C {
function g(string calldata) external {}
function main() view external {
function (string memory) external ptr = this.g;
ptr;
}
}
// ----

View File

@ -0,0 +1,9 @@
contract C {
function g(bytes calldata b) pure internal {}
function main() pure external {
function (bytes calldata) internal ptr = g;
ptr;
}
}
// ----