diff --git a/docs/contracts/using-for.rst b/docs/contracts/using-for.rst index 7da1ffd23..782519644 100644 --- a/docs/contracts/using-for.rst +++ b/docs/contracts/using-for.rst @@ -18,26 +18,20 @@ at contract level. The first part, ``A``, can be one of: -- A list of file-level or library functions (e.g. ``using {f, g, h, L.t} for uint;``) - - only those functions will be attached to the type as member functions. - Note that private library functions can only be specified when ``using for`` is inside the library. +- A list of file-level or library functions, optionally with an operator name assigned (e.g. + ``using {f, g as +, h, L.t as -} for uint;``). + If no operator is specified, the function is attached to the type as a member function, otherwise + it becomes the definition of that operator on the type. - The name of a library (e.g. ``using L for uint;``) - all non-private functions of the library are attached to the type as member functions -- a list of assignments of file-level or public/internal/private library functions to operators - (e.g. ``using {f as +, g as -} for T;``) - the functions will be attached to the type (``T``) - as operators. The following binary operators are allowed to be used on the list: ``|``, - ``^``, ``&``, ``+``, ``-``, ``*``, ``/``, ``%``, ``==``, ``!=``, ``<``, ``>``, ``<=``, - ``>=``, ``<<``, ``>>``, ``**``. Allowed unary operators are: ``~``, ``!``, ``-``. - If an operator can be both binary and unary, it is allowed to have each variant specified - on the list (e.g. ``using {sub as -, unsub as -} for T``). At file level, the second part, ``B``, has to be an explicit type (without data location specifier). Inside contracts, you can also use ``*`` in place of the type (e.g. ``using L for *;``), which has the effect that all functions of the library ``L`` are attached to *all* types. -If you specify a library, *all* functions in the library get attached, +If you specify a library, *all* non-private functions in the library get attached, even those where the type of the first parameter does not match the type of the object. The type is checked at the point the function is called and function overload @@ -47,11 +41,34 @@ If you use a list of functions (e.g. ``using {f, g, h, L.t} for uint;``), then the type (``uint``) has to be implicitly convertible to the first parameter of each of these functions. This check is performed even if none of these functions are called. +Note that private library functions can only be specified when ``using for`` is inside a library. -If you define an operator for a user-defined type (``using {f as +} for T``), then -the type (``T``), types of function parameters and the type of the function return value -have to be the same. One exception from this is the result type of comparison operators -for which it is always ``bool``. +If you define an operator (e.g. ``using {f as +} for T``), then the type (``T``) must be a +:ref:`user-defined value type `. +The definition of an operator must be a function with the types of all parameters and +the return value matching ``T``, except for comparison operators, where the return value must +be of type ``bool``. + +The following operators can be defined this way: + ++------------+---------+----------------------------------------------+ +| Category | Arity | Operators | ++============+=========+==============================================+ +| Bitwise | binary | ``&``, ``|``, ``^``, ``<<``, ``>>`` | +| +---------+----------------------------------------------+ +| | unary | ``~`` | ++------------+---------+----------------------------------------------+ +| Arithmetic | binary | ``+``, ``-``, ``*``, ``/``, ``%``, ``**`` | +| +---------+----------------------------------------------+ +| | unary | ``-`` | ++------------+---------+----------------------------------------------+ +| Comparison | binary | ``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=`` | ++------------+---------+----------------------------------------------+ +| Boolean | unary | ``!`` | ++------------+---------+----------------------------------------------+ + +Note that ``-`` is both binary and unary. +Whether the definition implements one or the other depends on the number of its arguments. The ``using A for B;`` directive is active only within the current scope (either the contract or the current module/source unit), diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 7181bef4d..c2688728f 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -653,8 +653,10 @@ private: * 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. * - * For version 4, T has to be user-defined value type. All parameters and - * return value of all the functions have to be of type T. + * For version 4, T has to be user-defined value type. + * 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 + * type and define operators on it at the same time. * * Finally, `using {f1, f2, ..., fn} for T global` is also valid at file level, as long as T is * a user-defined type defined in the same file at file level. In this case, the methods are