diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 28cc69a04..fef0ed27a 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1859,12 +1859,15 @@ void TypeChecker::endVisit(BinaryOperation const& _operation) commonType = builtinResult.get(); else if (userDefinedOperatorResult) { - solAssert( - userDefinedFunctionType->parameterTypes().size() == 2 && - *userDefinedFunctionType->parameterTypes().at(0) == - *userDefinedFunctionType->parameterTypes().at(1) - ); - if (userDefinedFunctionType->returnParameterTypes().size() == 1) + if (userDefinedFunctionType->parameterTypes().size() != 2 || + *userDefinedFunctionType->parameterTypes().at(0) != *userDefinedFunctionType->parameterTypes().at(1)) + m_errorReporter.typeError( + 5653_error, + _operation.location(), + "User defined operator " + string(TokenTraits::toString(_operation.getOperator())) + + " needs to have two parameters of equal type." + ); + else if (userDefinedFunctionType->returnParameterTypes().size() == 1) commonType = userDefinedFunctionType->parameterTypes().at(0); } diff --git a/test/libsolidity/syntaxTests/operators/custom/operator_with_calldata_parameters.sol b/test/libsolidity/syntaxTests/operators/custom/operator_with_calldata_parameters.sol index 7b33b691b..811165f31 100644 --- a/test/libsolidity/syntaxTests/operators/custom/operator_with_calldata_parameters.sol +++ b/test/libsolidity/syntaxTests/operators/custom/operator_with_calldata_parameters.sol @@ -1,4 +1,12 @@ -using {add as +} for S; +using { + add as +, + sub as -, + mul as *, + div as /, + mod as %, + unsub as -, + bitnot as ~ +} for S; struct S { uint x; @@ -9,3 +17,54 @@ function add(S calldata, S calldata) pure returns (S calldata r) { r := 0 } } + +function sub(S calldata, uint) pure returns (S calldata r) { + assembly { + r := 0 + } +} + +function mul(S calldata) pure returns (S calldata r) { + assembly { + r := 0 + } +} + +function div(S calldata, S calldata) pure returns (uint) { + return 0; +} + +function mod(S calldata, S calldata) pure { +} + +function unsub(uint) pure returns (S calldata r) { + assembly { + r := 0 + } +} + +function bitnot(S calldata) pure { +} + +function test(S calldata s) pure { + s + s; + s - s; + s * s; + s / s; + s % s; + -s; + ~s; +} + +// ---- +// TypeError 1884: (40-43): The function "mul" needs to have two parameters of equal type to be used for the operator *. +// TypeError 7743: (54-57): The function "div" needs to return exactly one value of type S to be used for the operator /. +// TypeError 7743: (68-71): The function "mod" needs to return exactly one value of type S to be used for the operator %. +// TypeError 3100: (82-87): The function "unsub" cannot be bound to the type "struct S storage pointer" because the type cannot be implicitly converted to the first argument of the function ("uint256"). +// TypeError 7743: (98-104): The function "bitnot" needs to return exactly one value of type S to be used for the operator ~. +// TypeError 5653: (747-752): User defined operator - needs to have two parameters of equal type. +// TypeError 2271: (758-763): Operator * not compatible with types struct S calldata and struct S calldata. No matching user-defined operator found. +// TypeError 3841: (769-774): User defined operator / needs to return value of type struct S calldata. +// TypeError 1208: (780-785): User defined operator % needs to return exactly one value. +// TypeError 4907: (791-793): Unary operator - cannot be applied to type struct S calldata. No matching user-defined operator found. +// TypeError 3138: (799-801): User defined operator ~ needs to return exactly one value. diff --git a/test/libsolidity/syntaxTests/operators/custom/operator_with_storage_parameters.sol b/test/libsolidity/syntaxTests/operators/custom/operator_with_storage_parameters.sol index d905104c8..c7d6b4616 100644 --- a/test/libsolidity/syntaxTests/operators/custom/operator_with_storage_parameters.sol +++ b/test/libsolidity/syntaxTests/operators/custom/operator_with_storage_parameters.sol @@ -1,4 +1,12 @@ -using {add as +} for S; +using { + add as +, + sub as -, + mul as *, + div as /, + mod as %, + unsub as -, + bitnot as ~ +} for S; struct S { uint x; @@ -8,11 +16,52 @@ function add(S storage a, S storage) pure returns (S storage) { return a; } +function sub(S storage a, uint) pure returns (S storage) { + return a; +} + +function mul(S storage a) pure returns (S storage) { + return a; +} + +function div(S storage a, S storage) pure returns (uint) { + return 0; +} + +function mod(S storage a, S storage) pure { +} + +function unsub(S storage a) pure { +} + +function bitnot(S storage a, S storage) pure returns (S storage) { + return a; +} + contract C { S a; S b; function test() public view { a + b; + a - b; + a * b; + a / b; + a % b; + -a; + ~a; } } +// ---- +// TypeError 1884: (40-43): The function "mul" needs to have two parameters of equal type to be used for the operator *. +// TypeError 7743: (54-57): The function "div" needs to return exactly one value of type S to be used for the operator /. +// TypeError 7743: (68-71): The function "mod" needs to return exactly one value of type S to be used for the operator %. +// TypeError 7743: (82-87): The function "unsub" needs to return exactly one value of type S to be used for the operator -. +// TypeError 1147: (98-104): The function "bitnot" needs to have exactly one parameter to be used for the operator ~. +// TypeError 5653: (707-712): User defined operator - needs to have two parameters of equal type. +// TypeError 3841: (707-712): User defined operator - needs to return value of type struct S storage ref. +// TypeError 2271: (722-727): Operator * not compatible with types struct S storage ref and struct S storage ref. No matching user-defined operator found. +// TypeError 3841: (737-742): User defined operator / needs to return value of type struct S storage pointer. +// TypeError 1208: (752-757): User defined operator % needs to return exactly one value. +// TypeError 3138: (767-769): User defined operator - needs to return exactly one value. +// TypeError 4907: (779-781): Unary operator ~ cannot be applied to type struct S storage ref. No matching user-defined operator found.