Tests/Docs after "stricter explicit conversion from Literals to Integers"

This commit is contained in:
hrkrshnn 2020-10-26 11:01:18 +01:00
parent a555556559
commit 29e23efc93
27 changed files with 90 additions and 76 deletions

View File

@ -9,7 +9,7 @@ Breaking Changes:
* Type System: Disallow explicit conversions from negative literals and literals larger than ``type(uint160).max`` to ``address`` type.
* Parser: Exponentiation is right associative. ``a**b**c`` is parsed as ``a**(b**c)``.
* Code Generator: Use ``revert`` with error signature ``Panic(uint256)`` and error codes instead of invalid opcode on failing assertions.
* Type System: Explicit conversions from literals to integer type is as strict as implicit conversions.
Language Features:
* Super constructors can now be called using the member notation e.g. ``M.C(123)``.

View File

@ -35,8 +35,10 @@ the compiler notifying you about it.
New Restrictions
================
* Explicit conversions from negative literals and literals larger
than ``type(uint160).max`` to ``address`` are disallowed.
* Explicit conversions from negative literals and literals larger than ``type(uint160).max`` to
``address`` are disallowed. Similarly, explicit conversions between literals and an integer type
``T`` are only allowed if the literal lies between ``type(T).min`` and ``type(T).max``. In
particular, replace usages of ``uint(-1)`` with ``type(uint).max``.
The previous behaviour was likely ambiguous.

View File

@ -126,7 +126,7 @@ custom types without the overhead of external function calls:
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.9.0;
pragma solidity >=0.6.8 <0.9.0;
struct bigint {
uint[] limbs;
@ -145,7 +145,7 @@ custom types without the overhead of external function calls:
uint a = limb(_a, i);
uint b = limb(_b, i);
r.limbs[i] = a + b + carry;
if (a + b < a || (a + b == uint(-1) && carry > 0))
if (a + b < a || (a + b == type(uint).max && carry > 0))
carry = 1;
else
carry = 0;
@ -175,7 +175,7 @@ custom types without the overhead of external function calls:
function f() public pure {
bigint memory x = BigInt.fromUint(7);
bigint memory y = BigInt.fromUint(uint(-1));
bigint memory y = BigInt.fromUint(type(uint).max);
bigint memory z = x.add(y);
assert(z.limb(1) > 0);
}

View File

@ -83,7 +83,7 @@ Let us rewrite the set example from the
It is also possible to extend elementary types in that way::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;
pragma solidity >=0.6.8 <0.9.0;
library Search {
function indexOf(uint[] storage self, uint value)
@ -93,7 +93,7 @@ It is also possible to extend elementary types in that way::
{
for (uint i = 0; i < self.length; i++)
if (self[i] == value) return i;
return uint(-1);
return type(uint).max;
}
}
@ -108,7 +108,7 @@ It is also possible to extend elementary types in that way::
function replace(uint _old, uint _new) public {
// This performs the library function call
uint index = data.indexOf(_old);
if (index == uint(-1))
if (index == type(uint).max)
data.push(_new);
else
data[index] = _new;

View File

@ -114,6 +114,11 @@ that is large enough to represent it without truncation::
uint32 b = 1234; // fine
uint16 c = 0x123456; // fails, since it would have to truncate to 0x3456
.. note::
Prior to version 0.8.0, any decimal or hexadecimal number literals could be explicitly
converted to an integer type. From 0.8.0, such explicit conversions are as strict as implicit
conversions, i.e., they are only allowed if the literal fits in the resulting range.
Fixed-Size Byte Arrays
----------------------

View File

@ -124,7 +124,7 @@ the ``sum`` function iterates over to sum all the values.
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.9.0;
pragma solidity >=0.6.8 <0.9.0;
struct IndexValue { uint keyIndex; uint value; }
struct KeyFlag { uint key; bool deleted; }
@ -165,7 +165,7 @@ the ``sum`` function iterates over to sum all the values.
}
function iterate_start(itmap storage self) internal view returns (uint keyIndex) {
return iterate_next(self, uint(-1));
return iterate_next(self, type(uint).max);
}
function iterate_valid(itmap storage self, uint keyIndex) internal view returns (bool) {

View File

@ -211,7 +211,7 @@ library strings {
}
if (a != b) {
// Mask out irrelevant bytes and check again
uint256 mask = uint256(-1); // 0xffff...
uint256 mask = type(uint256).max; // 0xffff...
if(shortest < 32) {
mask = ~(2 ** (8 * (32 - shortest + idx)) - 1);
}

View File

@ -39,7 +39,7 @@ function colony_test
cd lib
rm -Rf dappsys
git clone https://github.com/solidity-external-tests/dappsys-monolithic.git -b master_060 dappsys
git clone https://github.com/solidity-external-tests/dappsys-monolithic.git -b master_080 dappsys
cd ..
truffle_run_test compile_fn test_fn

View File

@ -761,7 +761,7 @@ BOOST_AUTO_TEST_CASE(return_dynamic_types_cross_call_advanced)
contract C {
function dyn() public returns (bytes memory a, uint b, bytes20[] memory c, uint d) {
a = "1234567890123456789012345678901234567890";
b = uint(-1);
b = type(uint).max;
c = new bytes20[](4);
c[0] = bytes20(uint160(1234));
c[3] = bytes20(uint160(6789));

View File

@ -70,7 +70,7 @@ BOOST_AUTO_TEST_CASE(value_types)
assembly { b := 7 }
C c;
assembly { c := sub(0, 5) }
emit E(10, uint16(uint256(-2)), uint24(0x12121212), int24(int256(-1)), bytes3(x), b, c);
emit E(10, uint16(type(uint).max - 1), uint24(uint(0x12121212)), int24(int256(-1)), bytes3(x), b, c);
}
}
)";
@ -189,7 +189,7 @@ BOOST_AUTO_TEST_CASE(memory_array_two_dim)
x[0] = new int16[](3);
x[1] = new int16[](2);
x[0][0] = 7;
x[0][1] = int16(0x010203040506);
x[0][1] = int16(int(0x010203040506));
x[0][2] = -1;
x[1][0] = 4;
x[1][1] = 5;

View File

@ -1061,9 +1061,9 @@ BOOST_AUTO_TEST_CASE(packed_keccak256_complex_types)
uint120[3] x;
function f() public returns (bytes32 hash1, bytes32 hash2, bytes32 hash3) {
uint120[] memory y = new uint120[](3);
x[0] = y[0] = uint120(-2);
x[1] = y[1] = uint120(-3);
x[2] = y[2] = uint120(-4);
x[0] = y[0] = uint120(type(uint).max - 1);
x[1] = y[1] = uint120(type(uint).max - 2);
x[2] = y[2] = uint120(type(uint).max - 3);
hash1 = keccak256(abi.encodePacked(x));
hash2 = keccak256(abi.encodePacked(y));
hash3 = keccak256(abi.encodePacked(this.f));
@ -4407,7 +4407,7 @@ BOOST_AUTO_TEST_CASE(internal_types_in_library)
for (uint i = 0; i < _haystack.length; ++i)
if (_haystack[i] == _needle)
return i;
return uint(-1);
return type(uint).max;
}
}
contract Test {
@ -6255,7 +6255,7 @@ BOOST_AUTO_TEST_CASE(abi_encode_with_selector)
}
function f3() public pure returns (bytes memory) {
bytes4 x = 0x12345678;
return abi.encodeWithSelector(x, uint(-1));
return abi.encodeWithSelector(x, type(uint).max);
}
}
)";
@ -6287,7 +6287,7 @@ BOOST_AUTO_TEST_CASE(abi_encode_with_selectorv2)
}
function f3() public pure returns (bytes memory) {
bytes4 x = 0x12345678;
return abi.encodeWithSelector(x, uint(-1));
return abi.encodeWithSelector(x, type(uint).max);
}
struct S { uint a; string b; uint16 c; }
function f4() public pure returns (bytes memory) {
@ -6296,7 +6296,7 @@ BOOST_AUTO_TEST_CASE(abi_encode_with_selectorv2)
s.a = 0x1234567;
s.b = "Lorem ipsum dolor sit ethereum........";
s.c = 0x1234;
return abi.encodeWithSelector(x, uint(-1), s, uint(3));
return abi.encodeWithSelector(x, type(uint).max, s, uint(3));
}
}
)";
@ -6336,10 +6336,10 @@ BOOST_AUTO_TEST_CASE(abi_encode_with_signature)
function f2() public pure returns (bytes memory r, uint[] memory ar) {
string memory x = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
uint[] memory y = new uint[](4);
y[0] = uint(-1);
y[1] = uint(-2);
y[2] = uint(-3);
y[3] = uint(-4);
y[0] = type(uint).max;
y[1] = type(uint).max - 1;
y[2] = type(uint).max - 2;
y[3] = type(uint).max - 3;
r = abi.encodeWithSignature(x, y);
// The hash uses temporary memory. This allocation re-uses the memory
// and should initialize it properly.
@ -6380,10 +6380,10 @@ BOOST_AUTO_TEST_CASE(abi_encode_with_signaturev2)
function f2() public pure returns (bytes memory r, uint[] memory ar) {
string memory x = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
uint[] memory y = new uint[](4);
y[0] = uint(-1);
y[1] = uint(-2);
y[2] = uint(-3);
y[3] = uint(-4);
y[0] = type(uint).max;
y[1] = type(uint).max - 1;
y[2] = type(uint).max - 2;
y[3] = type(uint).max - 3;
r = abi.encodeWithSignature(x, y);
// The hash uses temporary memory. This allocation re-uses the memory
// and should initialize it properly.
@ -6396,7 +6396,7 @@ BOOST_AUTO_TEST_CASE(abi_encode_with_signaturev2)
s.a = 0x1234567;
s.b = "Lorem ipsum dolor sit ethereum........";
s.c = 0x1234;
return abi.encodeWithSignature(s.b, uint(-1), s, uint(3));
return abi.encodeWithSignature(s.b, type(uint).max, s, uint(3));
}
}
)T";

View File

@ -348,7 +348,7 @@ BOOST_AUTO_TEST_CASE(incorrect_storage_access_bug)
function f() public returns (uint)
{
if (data[block.timestamp] == 0)
data[uint(-7)] = 5;
data[type(uint).max - 6] = 5;
return data[block.timestamp];
}
}
@ -696,11 +696,11 @@ BOOST_AUTO_TEST_CASE(shift_optimizer_bug)
{
function f(uint x) public returns (uint)
{
return (x << 1) << uint(-1);
return (x << 1) << type(uint).max;
}
function g(uint x) public returns (uint)
{
return (x >> 1) >> uint(-1);
return (x >> 1) >> type(uint).max;
}
}
)";

View File

@ -15,7 +15,7 @@ contract BinarySearch {
uint256 _value
) private returns (uint256 o_position) {
if (_len == 0 || (_len == 1 && _data[_begin] != _value))
return uint256(-1); // failure
return type(uint256).max; // failure
uint256 halfLen = _len / 2;
uint256 v = _data[_begin + halfLen];
if (_value < v) return find(_data, _begin, halfLen, _value);

View File

@ -1,7 +1,8 @@
contract C {
function f() public pure returns (uint8 x) {
unchecked {
return uint8(0x166)**uint8(uint8(2)**uint8(8));
uint16 x = 0x166;
return uint8(x)**uint8(uint8(2)**uint8(8));
}
}
}

View File

@ -3,7 +3,7 @@ contract C {
// (v should be 27 or 28, not 1)
// Note that the precompile does not return zero but returns nothing.
function f() public returns (address) {
return ecrecover(bytes32(uint(-1)), 1, bytes32(uint(2)), bytes32(uint(3)));
return ecrecover(bytes32(type(uint256).max), 1, bytes32(uint(2)), bytes32(uint(3)));
}
}
// ====

View File

@ -2,7 +2,7 @@ contract c {
enum Truth {False, True}
function test() public returns (uint256) {
return uint256(Truth(uint8(0x701)));
return uint256(Truth(uint8(0x1)));
}
}

View File

@ -1,7 +1,7 @@
contract Test {
function test() public returns (uint ret) { return uint(address(uint128(0x11223344556677889900112233445566778899001122))); }
function test() public returns (uint ret) { return uint(address(uint128(type(uint200).max))); }
}
// ====
// compileViaYul: also
// ----
// test() -> 158887387085137674884660775897412931874
// test() -> 0xffffffffffffffffffffffffffffffff

View File

@ -1,6 +1,6 @@
contract C {
function f() public pure returns (uint16 x) {
uint8 y = uint8(0x12345678);
uint8 y = uint8(0x78);
x = y;
}
}

View File

@ -6,8 +6,8 @@ contract C {
function test_simple(uint _off) public returns (uint _a, uint _b, uint _c) {
simple[_off + 2] = 3;
simple[_off + 3] = 4;
simple[uint(-1)] = 5;
_c = simple[uint(-1)];
simple[type(uint256).max] = 5;
_c = simple[type(uint256).max];
_b = simple[3 + _off];
_a = simple[2 + _off];
}

View File

@ -2,7 +2,7 @@ pragma experimental SMTChecker;
contract C {
function f() public pure {
uint x = uint(~1);
uint x = type(uint256).max - 1;
assert(x == 2**256 - 2);
assert(~1 == -2);
}

View File

@ -5,23 +5,23 @@ contract C {
// signed <- signed
int8 z = int8(-1);
assert(z == -1);
z = int8(0xf0ff);
z = int8(int(0) - 1);
assert(z == -1);
z = int8(0xcafecafef0ff);
z = int8(int(0) - 1);
assert(z == -1);
z = int8(0xcafecafe);
z = int8(int(0) - 2);
assert(z == -2);
z = int8(255);
z = int8(int(0) - 1);
assert(z == -1);
// unsigned <= unsigned
uint8 x = uint8(uint16(-1));
uint8 x = uint8(type(uint256).max);
assert(x == 255);
x = uint8(uint256(-1));
x = uint8(type(uint256).max);
assert(x == 255);
// signed <- unsigned
int8 y = int8(uint16(-1));
int8 y = int8(type(uint16).max);
assert(y == -1);
y = int8(uint16(100));
assert(y == 100);
@ -29,7 +29,7 @@ contract C {
assert(y == -56);
// unsigned <- signed
uint8 v = uint8(int16(-1));
uint8 v = uint8(type(uint16).max);
assert(v == 255);
v = uint8(int16(300));
assert(v == 44);

View File

@ -10,7 +10,7 @@ contract C {
}
function g() public pure {
uint a = uint(0);
uint b = uint(-1);
uint b = type(uint256).max;
uint c = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
int d = -1;
uint e = uint(d);
@ -20,7 +20,7 @@ contract C {
}
function h() public pure {
uint32 a = uint32(0);
uint32 b = uint32(-1);
uint32 b = type(uint32).max;
uint32 c = 4294967295;
int32 d = -1;
uint32 e = uint32(d);

View File

@ -11,7 +11,7 @@ contract C {
assert(x == -56);
int256 y = int256(uint256(2**255 + 10));
assert(y == -(2**255) + 10);
int256 z = int256(2**255 + 10);
int256 z = int256(uint(2**255 + 10));
assert(z == -(2**255) + 10);
int256 t = int256(bytes32(uint256(200)));
assert(t == 200);
@ -30,17 +30,17 @@ contract C {
// unsigned <- signed
uint8 x = uint8(int8(100));
assert(x == 100);
uint8 y = uint8(int8(200));
uint16 y = uint16(int16(200));
assert(y == 200);
uint8 z = uint8(int8(-100));
assert(z == 156);
uint8 t = uint8(int8(-200));
assert(t == 56);
uint16 t = uint16(int16(-200));
assert(t == type(uint16).max - 200 + 1);
uint256 v = uint256(int256(-200));
assert(v == 2**256 - 200);
uint256 w = uint256(-2);
uint256 w = uint256(type(uint256).max - 1);
assert(w == 2**256 - 2);
bytes4 b = bytes4(uint32(-2));
bytes4 b = bytes4(uint32(type(uint256).max - 1));
assert(uint32(b) == uint32(2**32 - 2));
address a = address(type(uint160).max);
assert(uint160(a) == uint160(2**160 - 1));
@ -71,4 +71,4 @@ contract C {
}
}
// ----
// Warning 8364: (1340-1341): Assertion checker does not yet implement type type(enum E)
// Warning 8364: (1414-1415): Assertion checker does not yet implement type type(enum E)

View File

@ -5,7 +5,7 @@ abstract contract D {}
contract C {
function f1() public pure {
// unsigned <- signed
uint16 x = uint16(-1);
uint16 x = type(uint16).max;
assert(x == 65535);
int8 i = int8(-1);
assert(i == -1);
@ -19,9 +19,9 @@ contract C {
function f2() public pure {
// signed <- unsigned
int16 y = int16(uint8(65535));
int16 y = int16(uint8(uint(65535)));
assert(y == 255);
int z = int(uint8(-1));
int z = int(uint8(type(uint).max));
assert(z == 255);
z = int(uint8(255));
assert(z == 255);
@ -29,11 +29,11 @@ contract C {
function f3() public pure {
// signed <- signed
int16 y = int16(int8(65535));
int16 y = int16(int8(uint(65535)));
assert(y == -1);
int z = int(int8(-1));
assert(z == -1);
z = int(int8(255));
z = int(int8(int(255)));
assert(z == -1);
z = int(int16(5000));
assert(z == 5000);
@ -41,15 +41,15 @@ contract C {
function f4() public pure {
// unsigned <- unsigned
uint x = uint(uint8(-1));
uint x = uint(uint8(type(uint).max));
assert(x == 255);
x = uint(uint16(-1));
x = uint(uint16(type(uint).max));
assert(x == 65535);
x = uint(uint16(5000));
assert(x == 5000);
uint16 y = uint16(-1);
uint16 y = uint16(type(uint).max);
assert(y == 65535);
y = uint16(uint8(-1));
y = uint16(uint8(type(uint16).max));
assert(y == 255);
address a = address(uint8(0));
assert(a == address(0));
@ -67,4 +67,4 @@ contract C {
}
}
// ----
// Warning 8364: (1144-1145): Assertion checker does not yet implement type type(contract D)
// Warning 8364: (1229-1230): Assertion checker does not yet implement type type(contract D)

View File

@ -3,7 +3,7 @@ contract C {
return address(2**160 -1);
}
function g() public pure returns (address) {
return address(uint(-1));
return address(type(uint160).max);
}
}
// ----

View File

@ -1,7 +1,9 @@
contract c {
function f() public pure {
uint a = -1;
uint b = uint(-1);
}
}
// ----
// TypeError 9574: (52-63): Type int_const -1 is not implicitly convertible to expected type uint256. Cannot implicitly convert signed literal to unsigned type.
// TypeError 9640: (82-90): Explicit type conversion not allowed from "int_const -1" to "uint256".

View File

@ -1,7 +1,11 @@
contract c {
contract C {
function f() public pure {
uint8 a = 256;
uint8 b = uint8(256);
int8 c = int8(-129);
}
}
// ----
// TypeError 9574: (52-65): Type int_const 256 is not implicitly convertible to expected type uint8. Literal is too large to fit in uint8.
// TypeError 9640: (85-95): Explicit type conversion not allowed from "int_const 256" to "uint8".
// TypeError 9640: (114-124): Explicit type conversion not allowed from "int_const -129" to "int8".