diff --git a/libsolidity/analysis/DeclarationTypeChecker.cpp b/libsolidity/analysis/DeclarationTypeChecker.cpp index e2f0cf6e8b00..4515203d9603 100644 --- a/libsolidity/analysis/DeclarationTypeChecker.cpp +++ b/libsolidity/analysis/DeclarationTypeChecker.cpp @@ -143,17 +143,35 @@ void DeclarationTypeChecker::endVisit(UserDefinedValueTypeDefinition const& _use { TypeName const* typeName = _userDefined.underlyingType(); solAssert(typeName, ""); - if (!dynamic_cast(typeName)) + + if ( + !dynamic_cast(typeName) && + !dynamic_cast(typeName) + ) m_errorReporter.fatalTypeError( 8657_error, typeName->location(), - "The underlying type for a user defined value type has to be an elementary value type." + "The underlying type for a user defined value type has to be an elementary value type or an internal function type." ); Type const* type = typeName->annotation().type; solAssert(type, ""); solAssert(!dynamic_cast(type), ""); - if (!type->isValueType()) + + if (auto const* funType = dynamic_cast(type)) + { + if (funType->kind() != FunctionType::Kind::Internal) + m_errorReporter.fatalTypeError( + 8657_error, + typeName->location(), + "The underlying type of the user defined value type \"" + + _userDefined.name() + + "\" has to be an internal function type, but \"" + + type->toString(true) + + "\" is an external function type." + ); + } + else if (!type->isValueType()) m_errorReporter.typeError( 8129_error, _userDefined.location(), diff --git a/test/libsolidity/semanticTests/userDefinedValueType/function_type_internal.sol b/test/libsolidity/semanticTests/userDefinedValueType/function_type_internal.sol new file mode 100644 index 000000000000..d264761d4b0b --- /dev/null +++ b/test/libsolidity/semanticTests/userDefinedValueType/function_type_internal.sol @@ -0,0 +1,38 @@ +library Hooks { + type Callback is function(uint256) returns (uint256); +} + +contract C { + Hooks.Callback cb; + + function double(uint256 x) internal pure returns (uint256) { + return x * 2; + } + + function triple(uint256 x) internal pure returns (uint256) { + return x * 3; + } + + function setCb(Hooks.Callback _cb) internal { + cb = _cb; + } + + function setup() public { + setCb(Hooks.Callback.wrap(double)); + } + + function callCb(uint256 x) public returns (uint256) { + function(uint256) returns (uint256) fn = Hooks.Callback.unwrap(cb); + return fn(x); + } + + function wrapAndCall(uint256 x) public returns (uint256) { + Hooks.Callback wrapped = Hooks.Callback.wrap(triple); + function(uint256) returns (uint256) fn = Hooks.Callback.unwrap(wrapped); + return fn(x); + } +} +// ---- +// setup() -> +// callCb(uint256): 5 -> 10 +// wrapAndCall(uint256): 7 -> 21 diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/all_value_types.sol b/test/libsolidity/syntaxTests/userDefinedValueType/all_value_types.sol index e1d453007ae8..be327671a8cf 100644 --- a/test/libsolidity/syntaxTests/userDefinedValueType/all_value_types.sol +++ b/test/libsolidity/syntaxTests/userDefinedValueType/all_value_types.sol @@ -9,5 +9,7 @@ type MyUfixed is ufixed; type MyFixedBytes32 is bytes32; type MyFixedBytes1 is bytes1; type MyBool is bool; +type MyCallback is function(uint256) returns (bool); +type MyPureFunction is function(uint256, uint256) pure returns (uint256); /// test to see if having NatSpec causes issues type redundantNatSpec is bytes2; diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/forward_reference_err.sol b/test/libsolidity/syntaxTests/userDefinedValueType/forward_reference_err.sol index 9ea93cb0902c..3c1dc091ed13 100644 --- a/test/libsolidity/syntaxTests/userDefinedValueType/forward_reference_err.sol +++ b/test/libsolidity/syntaxTests/userDefinedValueType/forward_reference_err.sol @@ -1,4 +1,4 @@ function f(MyIntB x) pure {} type MyIntB is MyIntB; // ---- -// TypeError 8657: (44-50): The underlying type for a user defined value type has to be an elementary value type. +// TypeError 8657: (44-50): The underlying type for a user defined value type has to be an elementary value type or an internal function type. diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/function_type_internal.sol b/test/libsolidity/syntaxTests/userDefinedValueType/function_type_internal.sol new file mode 100644 index 000000000000..7093bfd7828c --- /dev/null +++ b/test/libsolidity/syntaxTests/userDefinedValueType/function_type_internal.sol @@ -0,0 +1,27 @@ +type Callback is function(uint256) returns (bool); + +library Hooks { + type BeforeSwap is function(uint256) returns (bool); +} + +contract C { + Hooks.BeforeSwap cb; + + function set(Hooks.BeforeSwap _cb) internal { + cb = _cb; + } + + function wrapUnwrap() internal pure { + function(uint256) returns (bool) raw; + Callback wrapped = Callback.wrap(raw); + function(uint256) returns (bool) unwrapped = Callback.unwrap(wrapped); + unwrapped; + } + + function wrapUnwrapLib() internal pure { + function(uint256) returns (bool) raw; + Hooks.BeforeSwap wrapped = Hooks.BeforeSwap.wrap(raw); + function(uint256) returns (bool) unwrapped = Hooks.BeforeSwap.unwrap(wrapped); + unwrapped; + } +} diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_contract_err.sol b/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_contract_err.sol index 5a86e92f996a..fbebd810a9eb 100644 --- a/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_contract_err.sol +++ b/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_contract_err.sol @@ -1,4 +1,4 @@ contract C {} type MyContract is C; // ---- -// TypeError 8657: (33-34): The underlying type for a user defined value type has to be an elementary value type. +// TypeError 8657: (33-34): The underlying type for a user defined value type has to be an elementary value type or an internal function type. diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_enum_err.sol b/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_enum_err.sol index f143bc509312..3a757f5a7a7a 100644 --- a/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_enum_err.sol +++ b/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_enum_err.sol @@ -2,4 +2,4 @@ enum E {A, B, C} type MyType is E; // ---- -// TypeError 8657: (33-34): The underlying type for a user defined value type has to be an elementary value type. +// TypeError 8657: (33-34): The underlying type for a user defined value type has to be an elementary value type or an internal function type. diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_function_err.sol b/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_function_err.sol index 78d9c70431e2..37253318314a 100644 --- a/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_function_err.sol +++ b/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_function_err.sol @@ -1,3 +1,3 @@ -type MyFunction is function(uint) returns (uint); +type MyFunction is function(uint) external returns (uint); // ---- -// TypeError 8657: (19-49): The underlying type for a user defined value type has to be an elementary value type. +// TypeError 8657: (19-58): The underlying type of the user defined value type "MyFunction" has to be an internal function type, but "function (uint256) external returns (uint256)" is an external function type. diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_mapping_err.sol b/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_mapping_err.sol index 9f894c521b80..068ea5de113c 100644 --- a/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_mapping_err.sol +++ b/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_mapping_err.sol @@ -1,3 +1,3 @@ type MyInt is mapping(uint => uint); // ---- -// TypeError 8657: (14-35): The underlying type for a user defined value type has to be an elementary value type. +// TypeError 8657: (14-35): The underlying type for a user defined value type has to be an elementary value type or an internal function type. diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_struct_err.sol b/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_struct_err.sol index 3a713a887691..14c7c44c1542 100644 --- a/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_struct_err.sol +++ b/test/libsolidity/syntaxTests/userDefinedValueType/non_value_type_struct_err.sol @@ -4,4 +4,4 @@ contract C { type MyType is S; } // ---- -// TypeError 8657: (52-53): The underlying type for a user defined value type has to be an elementary value type. +// TypeError 8657: (52-53): The underlying type for a user defined value type has to be an elementary value type or an internal function type. diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/recursive_err.sol b/test/libsolidity/syntaxTests/userDefinedValueType/recursive_err.sol index 4130edde5d9a..8fd3dd1e067f 100644 --- a/test/libsolidity/syntaxTests/userDefinedValueType/recursive_err.sol +++ b/test/libsolidity/syntaxTests/userDefinedValueType/recursive_err.sol @@ -1,4 +1,4 @@ type MyInt1 is MyInt2; type MyInt2 is MyInt1; // ---- -// TypeError 8657: (15-21): The underlying type for a user defined value type has to be an elementary value type. +// TypeError 8657: (15-21): The underlying type for a user defined value type has to be an elementary value type or an internal function type. diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/recursive_function_parameter_err.sol b/test/libsolidity/syntaxTests/userDefinedValueType/recursive_function_parameter_err.sol index 52e99311e4ad..771efd3062ff 100644 --- a/test/libsolidity/syntaxTests/userDefinedValueType/recursive_function_parameter_err.sol +++ b/test/libsolidity/syntaxTests/userDefinedValueType/recursive_function_parameter_err.sol @@ -1,3 +1,3 @@ type MyFunction is function(MyFunction) external returns(MyFunction); // ---- -// TypeError 8657: (19-69): The underlying type for a user defined value type has to be an elementary value type. +// TypeError 8657: (19-69): The underlying type of the user defined value type "MyFunction" has to be an internal function type, but "function (MyFunction) external returns (MyFunction)" is an external function type. diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/self_reference_err.sol b/test/libsolidity/syntaxTests/userDefinedValueType/self_reference_err.sol index 20c657c7341a..08ef1cca3285 100644 --- a/test/libsolidity/syntaxTests/userDefinedValueType/self_reference_err.sol +++ b/test/libsolidity/syntaxTests/userDefinedValueType/self_reference_err.sol @@ -1,3 +1,3 @@ type MyInt is MyInt; // ---- -// TypeError 8657: (14-19): The underlying type for a user defined value type has to be an elementary value type. +// TypeError 8657: (14-19): The underlying type for a user defined value type has to be an elementary value type or an internal function type.