Adjusts documentation to read-only array length.

This commit is contained in:
Erik Kundt 2019-09-18 15:38:59 +02:00
parent 7d6c0a50c2
commit a69a344d70
4 changed files with 27 additions and 20 deletions

View File

@ -26,6 +26,10 @@ This section lists purely syntactic changes that do not affect the behavior of e
* Libraries have to implement all their functions, not only the internal ones. * Libraries have to implement all their functions, not only the internal ones.
* Member-access to ``length`` of arrays is now always read-only, even for storage arrays. It's no
longer possible to resize storage arrays assigning a new value to their length. Use ``push()``,
``push(value)`` or ``pop()`` instead, or assign a full array, which will of course overwrite existing content.
* New reserved keywords: ``virtual``. * New reserved keywords: ``virtual``.
* The names of variables declared in inline assembly may no longer end in ``_slot`` or ``_offset``. * The names of variables declared in inline assembly may no longer end in ``_slot`` or ``_offset``.
@ -75,6 +79,9 @@ This section gives detailed instructions on how to update prior code for every b
* Change ``uint length = array.push(value)`` to ``array.push(value);``. The new length can be * Change ``uint length = array.push(value)`` to ``array.push(value);``. The new length can be
accessed via ``array.length``. accessed via ``array.length``.
* Change ``array.length++`` to ``array.push()`` to increase, and use ``pop()`` to decrease
the length of a storage array.
* For every named return parameter in a function's ``@dev`` documentation define a ``@return`` * For every named return parameter in a function's ``@dev`` documentation define a ``@return``
entry which contains the parameter's name as the first word. E.g. if you have function ``f()`` defined entry which contains the parameter's name as the first word. E.g. if you have function ``f()`` defined
like ``function f() public returns (uint value)`` and a ``@dev`` annotating it, document its return like ``function f() public returns (uint value)`` and a ``@dev`` annotating it, document its return
@ -85,6 +92,7 @@ This section gives detailed instructions on how to update prior code for every b
* Add ``virtual`` to every non-interface function you intend to override. For single inheritance, add ``override`` to every overriding function. For multiple inheritance, add ``override(A, B, ..)``, where you list all contracts that define the overridden function in the brackets. When multiple bases define the same function, the inheriting contract must override all conflicting functions. * Add ``virtual`` to every non-interface function you intend to override. For single inheritance, add ``override`` to every overriding function. For multiple inheritance, add ``override(A, B, ..)``, where you list all contracts that define the overridden function in the brackets. When multiple bases define the same function, the inheriting contract must override all conflicting functions.
New Features New Features
============ ============

View File

@ -231,7 +231,7 @@ groupings of expressions.
pragma solidity >0.4.23 <0.7.0; pragma solidity >0.4.23 <0.7.0;
contract C { contract C {
uint[] data; uint index;
function f() public pure returns (uint, bool, uint) { function f() public pure returns (uint, bool, uint) {
return (7, true, 2); return (7, true, 2);
@ -244,7 +244,7 @@ groupings of expressions.
// Common trick to swap values -- does not work for non-value storage types. // Common trick to swap values -- does not work for non-value storage types.
(x, y) = (y, x); (x, y) = (y, x);
// Components can be left out (also for variable declarations). // Components can be left out (also for variable declarations).
(data.length, , ) = f(); // Sets the length to 7 (index, , ) = f(); // Sets the index to 7
} }
} }

View File

@ -278,7 +278,8 @@ a ``mapping``.
mapping (uint => uint)[] array; mapping (uint => uint)[] array;
function allocate(uint _newMaps) public { function allocate(uint _newMaps) public {
array.length += _newMaps; for (uint i = 0; i < _newMaps; i++)
array.push();
} }
function writeMap(uint _map, uint _key, uint _value) public { function writeMap(uint _map, uint _key, uint _value) public {

View File

@ -59,7 +59,7 @@ Data locations are not only relevant for persistency of data, but also for the s
x = memoryArray; // works, copies the whole array to storage x = memoryArray; // works, copies the whole array to storage
uint[] storage y = x; // works, assigns a pointer, data location of y is storage uint[] storage y = x; // works, assigns a pointer, data location of y is storage
y[7]; // fine, returns the 8th element y[7]; // fine, returns the 8th element
y.length = 2; // fine, modifies x through y y.pop(); // fine, modifies x through y
delete x; // fine, clears the array, also modifies y delete x; // fine, clears the array, also modifies y
// The following does not work; it would need to create a new temporary / // The following does not work; it would need to create a new temporary /
// unnamed array in storage, but storage is "statically" allocated: // unnamed array in storage, but storage is "statically" allocated:
@ -215,12 +215,6 @@ Array Members
**length**: **length**:
Arrays have a ``length`` member that contains their number of elements. Arrays have a ``length`` member that contains their number of elements.
The length of memory arrays is fixed (but dynamic, i.e. it can depend on runtime parameters) once they are created. The length of memory arrays is fixed (but dynamic, i.e. it can depend on runtime parameters) once they are created.
For dynamically-sized arrays (only available for storage), this member can be assigned to resize the array.
Accessing elements outside the current length does not automatically resize the array and instead causes a failing assertion.
Increasing the length adds new zero-initialised elements to the array.
Reducing the length performs an implicit :ref:`delete<delete>` on each of the
removed elements. If you try to resize a non-dynamic array that isn't in
storage, you receive a ``Value must be an lvalue`` error.
**push**: **push**:
Dynamic storage arrays and ``bytes`` (not ``string``) have a member function called ``push`` that you can use to append an element at the end of the array. Dynamic storage arrays and ``bytes`` (not ``string``) have a member function called ``push`` that you can use to append an element at the end of the array.
If no argument is given, the element will be zero-initialised and a reference to the new element is returned. If no argument is given, the element will be zero-initialised and a reference to the new element is returned.
@ -228,14 +222,11 @@ Array Members
**pop**: **pop**:
Dynamic storage arrays and ``bytes`` (not ``string``) have a member function called ``pop`` that you can use to remove an element from the end of the array. This also implicitly calls :ref:`delete<delete>` on the removed element. Dynamic storage arrays and ``bytes`` (not ``string``) have a member function called ``pop`` that you can use to remove an element from the end of the array. This also implicitly calls :ref:`delete<delete>` on the removed element.
.. warning::
If you use ``.length--`` on an empty array, it causes an underflow and
thus sets the length to ``2**256-1``.
.. note:: .. note::
Increasing the length of a storage array has constant gas costs because Increasing the length of a storage array by calling ``push()``
storage is assumed to be zero-initialised, while decreasing has constant gas costs because storage is zero-initialised,
the length has at least linear cost (but in most cases worse than linear), while decreasing the length by calling ``pop()`` has at least
linear cost (but in most cases worse than linear),
because it includes explicitly clearing the removed because it includes explicitly clearing the removed
elements similar to calling :ref:`delete<delete>` on them. elements similar to calling :ref:`delete<delete>` on them.
@ -295,7 +286,13 @@ Array Members
function changeFlagArraySize(uint newSize) public { function changeFlagArraySize(uint newSize) public {
// if the new size is smaller, removed array elements will be cleared // if the new size is smaller, removed array elements will be cleared
m_pairsOfFlags.length = newSize; if (newSize < m_pairsOfFlags.length) {
while (m_pairsOfFlags.length > newSize)
m_pairsOfFlags.pop();
} else if (newSize > m_pairsOfFlags.length) {
while (m_pairsOfFlags.length < newSize)
m_pairsOfFlags.push();
}
} }
function clear() public { function clear() public {
@ -303,7 +300,7 @@ Array Members
delete m_pairsOfFlags; delete m_pairsOfFlags;
delete m_aLotOfIntegers; delete m_aLotOfIntegers;
// identical effect here // identical effect here
m_pairsOfFlags.length = 0; m_pairsOfFlags = new bool[2][](0);
} }
bytes m_byteData; bytes m_byteData;
@ -312,7 +309,8 @@ Array Members
// byte arrays ("bytes") are different as they are stored without padding, // byte arrays ("bytes") are different as they are stored without padding,
// but can be treated identical to "uint8[]" // but can be treated identical to "uint8[]"
m_byteData = data; m_byteData = data;
m_byteData.length += 7; for (uint i = 0; i < 7; i++)
m_byteData.push();
m_byteData[3] = 0x08; m_byteData[3] = 0x08;
delete m_byteData[2]; delete m_byteData[2];
} }