aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/frequently-asked-questions.rst19
-rw-r--r--docs/types.rst95
2 files changed, 103 insertions, 11 deletions
diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst
index b26ff527..2c5f8661 100644
--- a/docs/frequently-asked-questions.rst
+++ b/docs/frequently-asked-questions.rst
@@ -446,6 +446,25 @@ does not fit inside this range, it is truncated. These truncations can have
above is necessary to avoid certain attacks.
+Why are explicit conversions between fixed-size bytes types and integer types failing?
+======================================================================================
+
+Since version 0.5.0 explicit conversions between fixed-size byte arrays and integers are only allowed,
+if both types have the same size. This prevents unexpected behaviour when truncating or padding.
+Such conversions are still possible, but intermediate casts are required that make the desired
+truncation and padding convention explicit. See :ref:`types-conversion-elementary-types` for a full
+explanation and examples.
+
+
+Why can number literals not be converted to fixed-size bytes types?
+===================================================================
+
+Since version 0.5.0 only hexadecimal number literals can be converted to fixed-size bytes
+types and only if the number of hex digits matches the size of the type. See :ref:`types-conversion-literals`
+for a full explanation and examples.
+
+
+
More Questions?
===============
diff --git a/docs/types.rst b/docs/types.rst
index 0e0f4b13..6024cbb7 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -1004,6 +1004,8 @@ It is important to note that ``delete a`` really behaves like an assignment to `
.. index:: ! type;conversion, ! cast
+.. _types-conversion-elementary-types:
+
Conversions between Elementary Types
====================================
@@ -1017,9 +1019,7 @@ is possible if it
makes sense semantically and no information is lost: ``uint8`` is convertible to
``uint16`` and ``int128`` to ``int256``, but ``int8`` is not convertible to ``uint256``
(because ``uint256`` cannot hold e.g. ``-1``).
-Furthermore, unsigned integers can be converted to bytes of the same or larger
-size, but not vice-versa. Any type that can be converted to ``uint160`` can also
-be converted to ``address``.
+Any integer type that can be converted to ``uint160`` can also be converted to ``address``.
Explicit Conversions
--------------------
@@ -1038,17 +1038,90 @@ a negative ``int8`` to a ``uint``:
At the end of this code snippet, ``x`` will have the value ``0xfffff..fd`` (64 hex
characters), which is -3 in the two's complement representation of 256 bits.
-If a type is explicitly converted to a smaller type, higher-order bits are
+If an integer is explicitly converted to a smaller type, higher-order bits are
cut off::
uint32 a = 0x12345678;
uint16 b = uint16(a); // b will be 0x5678 now
-Since 0.5.0 explicit conversions between integers and fixed-size byte arrays
-are only allowed, if both have the same size. To convert between integers and
-fixed-size byte arrays of different size, they first have to be explicitly
-converted to a matching size. This makes alignment and padding explicit::
+If an integer is explicitly converted to a larger type, it is padded on the left (i.e. at the higher order end).
+The result of the conversion will compare equal to the original integer.
+
+ uint16 a = 0x1234;
+ uint32 b = uint32(a); // b will be 0x00001234 now
+ assert(a == b);
+
+Fixed-size bytes types behave differently during conversions. They can be thought of as
+sequences of individual bytes and converting to a smaller type will cut off the
+sequence::
+
+ bytes2 a = 0x1234;
+ bytes1 b = bytes1(a); // b will be 0x12
+
+If a fixed-size bytes type is explicitly converted to a larger type, it is padded on
+the right. Accessing the byte at a fixed index will result in the same value before and
+after the conversion (if the index is still in range)::
+
+ bytes2 a = 0x1234;
+ bytes4 b = bytes4(a); // b will be 0x12340000
+ assert(a[0] == b[0]);
+ assert(a[1] == b[1]);
+
+Since integers and fixed-size byte arrays behave differently when truncating or
+padding, explicit conversions between integers and fixed-size byte arrays are only allowed,
+if both have the same size. If you want to convert between integers and fixed-size byte arrays of
+different size, you have to use intermediate conversions that make the desired truncation and padding
+rules explicit::
+
+ bytes2 a = 0x1234;
+ uint32 b = uint16(a); // b will be 0x00001234
+ uint32 c = uint32(bytes4(a)); // c will be 0x12340000
+ uint8 d = uint8(uint16(a)); // d will be 0x34
+ uint8 e = uint8(bytes1(a)); // d will be 0x12
+
+.. _types-conversion-literals:
+
+Conversions between Literals and Elementary Types
+=================================================
+
+Integer Types
+-------------
+
+Decimal and hexadecimal number literals can be implicitly converted to any integer type
+that is large enough to represent it without truncation::
+
+ uint8 a = 12; // fine
+ uint32 b = 1234; // fine
+ uint16 c = 0x123456; // fails, since it would have to truncate to 0x3456
+
+Fixed-Size Byte Arrays
+----------------------
- uint16 x = 0xffff;
- bytes32(uint256(x)); // pad on the left
- bytes32(bytes2(x)); // pad on the right
+Decimal number literals cannot be implicitly converted to fixed-size byte arrays. Hexadecimal
+number literals can be, but only if the number of hex digits exactly fits the size of the bytes
+type. As an exception both decimal and hexadecimal literals which have a value of zero can be
+converted to any fixed-size bytes type::
+
+ bytes2 a = 54321; // not allowed
+ bytes2 b = 0x12; // not allowed
+ bytes2 c = 0x123; // not allowed
+ bytes2 d = 0x1234; // fine
+ bytes2 e = 0x0012; // fine
+ bytes4 f = 0; // fine
+ bytes4 g = 0x0; // fine
+
+String literals and hex string literals can be implicitly converted to fixed-size byte arrays,
+if their number of characters matches the size of the bytes type::
+
+ bytes2 a = hex"1234"; // fine
+ bytes2 b = "xy"; // fine
+ bytes2 c = hex"12"; // not allowed
+ bytes2 d = hex"123"; // not allowed
+ bytes2 e = "x"; // not allowed
+ bytes2 f = "xyz"; // not allowed
+
+Addresses
+---------
+
+As described in :ref:`address_literals`, hex literals of the correct size that pass the checksum
+test are of ``address`` type. No other literals can be implicitly converted to the ``address`` type.