From 7fedb63dd339939154108f0219860a840bb0726a Mon Sep 17 00:00:00 2001 From: wechman Date: Fri, 8 Jul 2022 07:56:59 +0200 Subject: [PATCH] Adjust type checking --- libsolidity/analysis/TypeChecker.cpp | 48 ++++++++++++++----- .../custom/addition_returning_bool.sol | 16 ------- .../operators/custom/all_operators.sol | 6 +-- ...ator_with_different_param_return_types.sol | 3 +- .../operator_wrong_number_params_return.sol | 10 ++-- ...tor_attached_to_two_arguments_function.sol | 18 +++++++ 6 files changed, 64 insertions(+), 37 deletions(-) delete mode 100644 test/libsolidity/semanticTests/operators/custom/addition_returning_bool.sol create mode 100644 test/libsolidity/syntaxTests/operators/custom/unary_operator_attached_to_two_arguments_function.sol diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 3d3ad0244..584a5932d 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3904,7 +3904,9 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) if ( ( - (TokenTraits::isBinaryOp(*operator_) && !TokenTraits::isUnaryOp(*operator_)) || TokenTraits::isCompareOp(*operator_) + (TokenTraits::isBinaryOp(*operator_) && !TokenTraits::isUnaryOp(*operator_)) || + *operator_ == Token::Add || + TokenTraits::isCompareOp(*operator_) ) && ( functionType->parameterTypesIncludingSelf().size() != 2 || @@ -3920,33 +3922,57 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) TokenTraits::friendlyName(*operator_) + "." ); - if ( - (isUnaryNegation || (TokenTraits::isUnaryOp(*operator_) && *operator_ != Token::Add)) && + else if ( + !TokenTraits::isBinaryOp(*operator_) && TokenTraits::isUnaryOp(*operator_) && functionType->parameterTypesIncludingSelf().size() != 1 + ) + m_errorReporter.typeError( + 1147_error, + path->location(), + "The function \"" + joinHumanReadable(path->path(), ".") + "\" "+ + "needs to have exactly one parameter to be used for the operator " + + TokenTraits::friendlyName(*operator_) + + "." + ); + else if ( + functionType->parameterTypesIncludingSelf().size() != 1 && + functionType->parameterTypesIncludingSelf().size() != 2 ) m_errorReporter.typeError( 8112_error, path->location(), "The function \"" + joinHumanReadable(path->path(), ".") + "\" "+ - "needs to have exactly one parameter to be used for the operator " + + "needs to have one or two parameters to be used for the operator " + TokenTraits::friendlyName(*operator_) + "." ); - Type const* expectedType = - TokenTraits::isCompareOp(*operator_) ? - dynamic_cast(TypeProvider::boolean()) : - functionType->parameterTypesIncludingSelf().at(0); if ( - functionType->returnParameterTypes().size() != 1 || - *functionType->returnParameterTypes().front() != *expectedType + TokenTraits::isCompareOp(*operator_) && + (functionType->returnParameterTypes().size() != 1 || *functionType->returnParameterTypes().front() != *TypeProvider::boolean()) + ) + m_errorReporter.typeError( + 7995_error, + path->location(), + "The function \"" + joinHumanReadable(path->path(), ".") + "\" "+ + "needs to return exactly one value of type bool" + + " to be used for the operator " + + TokenTraits::friendlyName(*operator_) + + "." + ); + else if ( + !TokenTraits::isCompareOp(*operator_) && + ( + functionType->returnParameterTypes().size() != 1 || + *functionType->returnParameterTypes().front() != *functionType->parameterTypesIncludingSelf().front() + ) ) m_errorReporter.typeError( 7743_error, path->location(), "The function \"" + joinHumanReadable(path->path(), ".") + "\" "+ "needs to return exactly one value of type " + - expectedType->toString(true) + + functionType->parameterTypesIncludingSelf().front()->humanReadableName() + " to be used for the operator " + TokenTraits::friendlyName(*operator_) + "." diff --git a/test/libsolidity/semanticTests/operators/custom/addition_returning_bool.sol b/test/libsolidity/semanticTests/operators/custom/addition_returning_bool.sol deleted file mode 100644 index dcfdbac3d..000000000 --- a/test/libsolidity/semanticTests/operators/custom/addition_returning_bool.sol +++ /dev/null @@ -1,16 +0,0 @@ -type MyInt is int; -using {add as +} for MyInt; - -function add(MyInt, MyInt) pure returns (bool) { - return true; -} - -contract C { - function f() public pure returns (bool t) { - t = MyInt.wrap(2) + MyInt.wrap(7); - } -} -// ==== -// compileViaYul: also -// ---- -// f() -> true diff --git a/test/libsolidity/semanticTests/operators/custom/all_operators.sol b/test/libsolidity/semanticTests/operators/custom/all_operators.sol index 33df2b851..607b6cf4f 100644 --- a/test/libsolidity/semanticTests/operators/custom/all_operators.sol +++ b/test/libsolidity/semanticTests/operators/custom/all_operators.sol @@ -23,8 +23,8 @@ function bitxor(Int, Int) pure returns (Int) { function bitnot(Int) pure returns (Int) { return w(13); } -function add(Int x, Int) pure returns (int128) { - return uw(x) + 10; +function add(Int x, Int) pure returns (Int) { + return w(uw(x) + 10); } function sub(Int, Int) pure returns (Int) { return w(15); @@ -66,7 +66,7 @@ contract C { function test_bitand() public pure returns (Int) { return w(1) | w(2); } function test_bitxor() public pure returns (Int) { return w(1) ^ w(2); } function test_bitnot() public pure returns (Int) { return ~w(1); } - function test_add(int128 x) public pure returns (int128) { return w(x) + w(2); } + function test_add(int128 x) public pure returns (Int) { return w(x) + w(2); } function test_sub() public pure returns (Int) { return w(1) - w(2); } function test_unsub() public pure returns (Int) { return -w(1); } function test_mul() public pure returns (Int) { return w(1) * w(2); } diff --git a/test/libsolidity/syntaxTests/operators/custom/operator_with_different_param_return_types.sol b/test/libsolidity/syntaxTests/operators/custom/operator_with_different_param_return_types.sol index 3a2fd769c..b14f28438 100644 --- a/test/libsolidity/syntaxTests/operators/custom/operator_with_different_param_return_types.sol +++ b/test/libsolidity/syntaxTests/operators/custom/operator_with_different_param_return_types.sol @@ -17,10 +17,9 @@ function mul(int128, int256) pure returns (Int) { } function div(Int, Int) pure returns (int256) { - return Int.wrap(3); + return 3; } // ---- // TypeError 3100: (42-45): The function "sub" cannot be bound to the type "Int" because the type cannot be implicitly converted to the first argument of the function ("int128"). // TypeError 3100: (56-59): The function "mul" cannot be bound to the type "Int" because the type cannot be implicitly converted to the first argument of the function ("int128"). // TypeError 7743: (66-69): The function "div" needs to return exactly one value of type Int to be used for the operator /. -// TypeError 6359: (365-376): Return argument type Int is not implicitly convertible to expected type (type of first return variable) int256. diff --git a/test/libsolidity/syntaxTests/operators/custom/operator_wrong_number_params_return.sol b/test/libsolidity/syntaxTests/operators/custom/operator_wrong_number_params_return.sol index 11ca1be53..81b6eb2f0 100644 --- a/test/libsolidity/syntaxTests/operators/custom/operator_wrong_number_params_return.sol +++ b/test/libsolidity/syntaxTests/operators/custom/operator_wrong_number_params_return.sol @@ -6,7 +6,7 @@ using { gt as >, lt as < } for Int; -function add(Int, Int) pure returns (Int) { +function add(Int) pure returns (Int) { return Int.wrap(0); } @@ -31,9 +31,9 @@ function lt(Int, Int) pure returns (bool, Int) { } // ---- -// TypeError 1884: (43-46): The function "sub" needs to have two parameters of equal type to be used for the operator -. -// TypeError 8112: (43-46): The function "sub" needs to have exactly one parameter to be used for the operator -. +// TypeError 1884: (33-36): The function "add" needs to have two parameters of equal type to be used for the operator +. +// TypeError 8112: (43-46): The function "sub" needs to have one or two parameters to be used for the operator -. // TypeError 1884: (57-60): The function "mul" needs to have two parameters of equal type to be used for the operator *. // TypeError 7743: (67-70): The function "div" needs to return exactly one value of type Int to be used for the operator /. -// TypeError 7743: (81-83): The function "gt" needs to return exactly one value of type bool to be used for the operator >. -// TypeError 7743: (90-92): The function "lt" needs to return exactly one value of type bool to be used for the operator <. +// TypeError 7995: (81-83): The function "gt" needs to return exactly one value of type bool to be used for the operator >. +// TypeError 7995: (90-92): The function "lt" needs to return exactly one value of type bool to be used for the operator <. diff --git a/test/libsolidity/syntaxTests/operators/custom/unary_operator_attached_to_two_arguments_function.sol b/test/libsolidity/syntaxTests/operators/custom/unary_operator_attached_to_two_arguments_function.sol new file mode 100644 index 000000000..02c6e8eb8 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/custom/unary_operator_attached_to_two_arguments_function.sol @@ -0,0 +1,18 @@ +type Int is int128; +using { + bitnot as ~ +} for Int; + +function bitnot(Int, Int) pure returns (Int) { + return Int.wrap(13); +} + +contract C { + function test() public pure { + ~Int.wrap(1); + } +} + +// ---- +// TypeError 1147: (32-38): The function "bitnot" needs to have exactly one parameter to be used for the operator ~. +// TypeError 4907: (186-198): Unary operator ~ cannot be applied to type Int