Disallow defining operators with non-pure functions

This commit is contained in:
Kamil Śliwak 2023-01-17 12:53:34 +01:00
parent 56ebb5f901
commit e0722732f6
7 changed files with 22 additions and 49 deletions

View File

@ -45,7 +45,7 @@ Note that private library functions can only be specified when ``using for`` is
If you define an operator (e.g. ``using {f as +} for T``), then the type (``T``) must be a If you define an operator (e.g. ``using {f as +} for T``), then the type (``T``) must be a
:ref:`user-defined value type <user-defined-value-types>`. :ref:`user-defined value type <user-defined-value-types>`.
The definition of an operator must be a function with the types of all parameters and The definition of an operator must be a ``pure`` function with the types of all parameters and
the return value matching ``T``, except for comparison operators, where the return value must the return value matching ``T``, except for comparison operators, where the return value must
be of type ``bool``. be of type ``bool``.

View File

@ -4001,6 +4001,13 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
} }
solAssert(usingForType->typeDefinition()); solAssert(usingForType->typeDefinition());
if (functionType->stateMutability() != StateMutability::Pure)
m_errorReporter.typeError(
7775_error,
path->location(),
"Only pure functions can be used to define operators."
);
bool identicalFirstTwoParameters = (parameterCount < 2 || *parameterTypes.at(0) == *parameterTypes.at(1)); bool identicalFirstTwoParameters = (parameterCount < 2 || *parameterTypes.at(0) == *parameterTypes.at(1));
bool isUnaryOnlyOperator = (!TokenTraits::isBinaryOp(*operator_) && TokenTraits::isUnaryOp(*operator_)); bool isUnaryOnlyOperator = (!TokenTraits::isBinaryOp(*operator_) && TokenTraits::isUnaryOp(*operator_));
bool isBinaryOnlyOperator = bool isBinaryOnlyOperator =

View File

@ -653,7 +653,7 @@ private:
* all functions, and this is checked at the point of the using statement. For versions 1 and * all functions, and this is checked at the point of the using statement. For versions 1 and
* 2, this check is only done when a function is called. * 2, this check is only done when a function is called.
* *
* For version 4, T has to be user-defined value type. * For version 4, T has to be user-defined value type and the function must be pure.
* All parameters and return value of all the functions have to be of type T. * All parameters and return value of all the functions have to be of type T.
* This version can be combined with version 3 - a single directive may attach functions to the * This version can be combined with version 3 - a single directive may attach functions to the
* type and define operators on it at the same time. * type and define operators on it at the same time.

View File

@ -21,5 +21,4 @@ contract C {
} }
} }
// ---- // ----
// test() -> 3 // TypeError 7775: (27-30): Only pure functions can be used to define operators.
// gas legacy: 119695

View File

@ -0,0 +1,12 @@
using {add as +, sub as -, mul as *} for A;
function add(A, A) view returns (A) {}
function sub(A, A) returns (A) {}
function mul(A, A) payable returns (A) {}
type A is address payable;
// ----
// TypeError 7775: (7-10): Only pure functions can be used to define operators.
// TypeError 7775: (17-20): Only pure functions can be used to define operators.
// TypeError 7775: (27-30): Only pure functions can be used to define operators.
// TypeError 9559: (118-159): Free functions cannot be payable.

View File

@ -1,17 +0,0 @@
type Int is uint8;
using {
add as +
} for Int;
function f_view() view {}
function add(Int, Int) view returns (Int) {
f_view();
return Int.wrap(0);
}
function f() view {
Int.wrap(0) + Int.wrap(0);
}

View File

@ -1,28 +0,0 @@
type Int is uint8;
using {
add as +
} for Int;
function f_view() view {}
function add(Int, Int) view returns (Int) {
f_view();
return Int.wrap(0);
}
function f() view {
Int.wrap(0) + Int.wrap(0);
}
function g() {
Int.wrap(0) + Int.wrap(0);
}
function h() pure {
Int.wrap(0) + Int.wrap(0);
}
// ----
// Warning 2018: (220-267): Function state mutability can be restricted to view
// TypeError 2527: (293-318): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".