From 8c0740748e291c2244e1af86aee26045bef7082c Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Wed, 29 Jun 2022 17:42:58 +0530 Subject: [PATCH] functions taking calldata args should be assignable to function pointers of same type --- docs/types/value-types.rst | 12 ++++++++++++ ...igned_to_function_pointers_with_memory_type.sol | 10 ++++++++++ ..._assigned_to_function_pointers_of_same_type.sol | 14 ++++++++++++++ ...igned_to_function_pointers_with_memory_type.sol | 9 +++++++++ ..._assigned_to_function_pointers_of_same_type.sol | 9 +++++++++ 5 files changed, 54 insertions(+) create mode 100644 test/libsolidity/semanticTests/functionTypes/external_functions_with_calldata_args_assigned_to_function_pointers_with_memory_type.sol create mode 100644 test/libsolidity/syntaxTests/functionTypes/external_functions_with_calldata_args_assigned_to_function_pointers_of_same_type.sol create mode 100644 test/libsolidity/syntaxTests/functionTypes/external_functions_with_calldata_args_assigned_to_function_pointers_with_memory_type.sol create mode 100644 test/libsolidity/syntaxTests/functionTypes/internal_functions_with_calldata_args_assigned_to_function_pointers_of_same_type.sol diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 1e8e3e7fd..cfec894a9 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -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 `. Functions declared in interfaces do not have definitions so pointing at them does not make sense either. diff --git a/test/libsolidity/semanticTests/functionTypes/external_functions_with_calldata_args_assigned_to_function_pointers_with_memory_type.sol b/test/libsolidity/semanticTests/functionTypes/external_functions_with_calldata_args_assigned_to_function_pointers_with_memory_type.sol new file mode 100644 index 000000000..069d257f7 --- /dev/null +++ b/test/libsolidity/semanticTests/functionTypes/external_functions_with_calldata_args_assigned_to_function_pointers_with_memory_type.sol @@ -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 diff --git a/test/libsolidity/syntaxTests/functionTypes/external_functions_with_calldata_args_assigned_to_function_pointers_of_same_type.sol b/test/libsolidity/syntaxTests/functionTypes/external_functions_with_calldata_args_assigned_to_function_pointers_of_same_type.sol new file mode 100644 index 000000000..b5bacb69b --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/external_functions_with_calldata_args_assigned_to_function_pointers_of_same_type.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/functionTypes/external_functions_with_calldata_args_assigned_to_function_pointers_with_memory_type.sol b/test/libsolidity/syntaxTests/functionTypes/external_functions_with_calldata_args_assigned_to_function_pointers_with_memory_type.sol new file mode 100644 index 000000000..8aab9fd18 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/external_functions_with_calldata_args_assigned_to_function_pointers_with_memory_type.sol @@ -0,0 +1,9 @@ +contract C { + function g(string calldata) external {} + + function main() view external { + function (string memory) external ptr = this.g; + ptr; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/functionTypes/internal_functions_with_calldata_args_assigned_to_function_pointers_of_same_type.sol b/test/libsolidity/syntaxTests/functionTypes/internal_functions_with_calldata_args_assigned_to_function_pointers_of_same_type.sol new file mode 100644 index 000000000..5e9014ada --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/internal_functions_with_calldata_args_assigned_to_function_pointers_of_same_type.sol @@ -0,0 +1,9 @@ +contract C { + function g(bytes calldata b) pure internal {} + + function main() pure external { + function (bytes calldata) internal ptr = g; + ptr; + } +} +// ----