mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #10224 from ethereum/strict-literal-to-enum-conversion
[BREAKING] Strict explicit conversion between literals and enums
This commit is contained in:
commit
3c1d990964
@ -10,6 +10,7 @@ Breaking Changes:
|
|||||||
* Parser: Exponentiation is right associative. ``a**b**c`` is parsed as ``a**(b**c)``.
|
* 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.
|
* 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.
|
* Type System: Explicit conversions from literals to integer type is as strict as implicit conversions.
|
||||||
|
* Type System: Explicit conversions from literals to enums are only allowed if the value fits in the enum.
|
||||||
|
|
||||||
Language Features:
|
Language Features:
|
||||||
* Super constructors can now be called using the member notation e.g. ``M.C(123)``.
|
* Super constructors can now be called using the member notation e.g. ``M.C(123)``.
|
||||||
|
@ -35,12 +35,16 @@ the compiler notifying you about it.
|
|||||||
New Restrictions
|
New Restrictions
|
||||||
================
|
================
|
||||||
|
|
||||||
* Explicit conversions from negative literals and literals larger than ``type(uint160).max`` to
|
* There are new restrictions related to explicit conversion of literals. The previous behaviour in
|
||||||
``address`` are disallowed. Similarly, explicit conversions between literals and an integer type
|
the following cases was likely ambiguous:
|
||||||
``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.
|
1. Explicit conversions from negative literals and literals larger than ``type(uint160).max`` to
|
||||||
|
``address`` are disallowed.
|
||||||
|
2. 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``.
|
||||||
|
3. Explicit conversions between literals and enums are only allowed if the literal can
|
||||||
|
represent a value in the enum.
|
||||||
|
|
||||||
* Function call options can only be given once, i.e. ``c.f{gas: 10000}{value: 1}()`` is invalid and has to be changed to ``c.f{gas: 10000, value: 1}()``.
|
* Function call options can only be given once, i.e. ``c.f{gas: 10000}{value: 1}()`` is invalid and has to be changed to ``c.f{gas: 10000, value: 1}()``.
|
||||||
|
|
||||||
|
@ -978,6 +978,9 @@ BoolResult RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo)
|
|||||||
}
|
}
|
||||||
else if (category == Category::Integer)
|
else if (category == Category::Integer)
|
||||||
return false;
|
return false;
|
||||||
|
else if (auto enumType = dynamic_cast<EnumType const*>(&_convertTo))
|
||||||
|
if (isNegative() || isFractional() || m_value >= enumType->numberOfMembers())
|
||||||
|
return false;
|
||||||
|
|
||||||
TypePointer mobType = mobileType();
|
TypePointer mobType = mobileType();
|
||||||
return (mobType && mobType->isExplicitlyConvertibleTo(_convertTo));
|
return (mobType && mobType->isExplicitlyConvertibleTo(_convertTo));
|
||||||
|
@ -13,8 +13,8 @@ contract test {
|
|||||||
d = uint256(choice);
|
d = uint256(choice);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getChoiceFromNegativeLiteral() public returns (uint256 d) {
|
function getChoiceFromMax() public returns (uint256 d) {
|
||||||
choice = ActionChoices(-1);
|
choice = ActionChoices(type(uint).max);
|
||||||
d = uint256(choice);
|
d = uint256(choice);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,8 +25,9 @@ contract test {
|
|||||||
// compileViaYul: also
|
// compileViaYul: also
|
||||||
// EVMVersion: >=byzantium
|
// EVMVersion: >=byzantium
|
||||||
// ----
|
// ----
|
||||||
|
// getChoiceExp(uint256): 2 -> 2
|
||||||
// getChoiceExp(uint256): 3 -> FAILURE, hex"4e487b71", 33 # These should throw #
|
// getChoiceExp(uint256): 3 -> FAILURE, hex"4e487b71", 33 # These should throw #
|
||||||
// getChoiceFromSigned(int256): -1 -> FAILURE, hex"4e487b71", 33
|
// getChoiceFromSigned(int256): -1 -> FAILURE, hex"4e487b71", 33
|
||||||
// getChoiceFromNegativeLiteral() -> FAILURE, hex"4e487b71", 33
|
// getChoiceFromMax() -> FAILURE, hex"4e487b71", 33
|
||||||
// getChoiceExp(uint256): 2 -> 2 # These should work #
|
// getChoiceExp(uint256): 2 -> 2 # These should work #
|
||||||
// getChoiceExp(uint256): 0 -> 0
|
// getChoiceExp(uint256): 0 -> 0
|
||||||
|
@ -13,8 +13,8 @@ contract test {
|
|||||||
d = uint256(choice);
|
d = uint256(choice);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getChoiceFromNegativeLiteral() public returns (uint256 d) {
|
function getChoiceFromMax() public returns (uint256 d) {
|
||||||
choice = ActionChoices(-1);
|
choice = ActionChoices(type(uint256).max);
|
||||||
d = uint256(choice);
|
d = uint256(choice);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,6 +27,6 @@ contract test {
|
|||||||
// ----
|
// ----
|
||||||
// getChoiceExp(uint256): 3 -> FAILURE # These should throw #
|
// getChoiceExp(uint256): 3 -> FAILURE # These should throw #
|
||||||
// getChoiceFromSigned(int256): -1 -> FAILURE
|
// getChoiceFromSigned(int256): -1 -> FAILURE
|
||||||
// getChoiceFromNegativeLiteral() -> FAILURE
|
// getChoiceFromMax() -> FAILURE
|
||||||
// getChoiceExp(uint256): 2 -> 2 # These should work #
|
// getChoiceExp(uint256): 2 -> 2 # These should work #
|
||||||
// getChoiceExp(uint256): 0 -> 0
|
// getChoiceExp(uint256): 0 -> 0
|
||||||
|
10
test/libsolidity/syntaxTests/enums/literal_conversion.sol
Normal file
10
test/libsolidity/syntaxTests/enums/literal_conversion.sol
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
contract C {
|
||||||
|
enum Test { One, Two }
|
||||||
|
function f() public pure {
|
||||||
|
Test a = Test(0);
|
||||||
|
Test b = Test(1);
|
||||||
|
Test c = Test(type(uint).max);
|
||||||
|
a; b; c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,16 @@
|
|||||||
|
contract C {
|
||||||
|
enum Test { One, Two }
|
||||||
|
function f() public {
|
||||||
|
Test(-1);
|
||||||
|
Test(2);
|
||||||
|
Test(13);
|
||||||
|
Test(5/3);
|
||||||
|
Test(0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 9640: (74-82): Explicit type conversion not allowed from "int_const -1" to "enum C.Test".
|
||||||
|
// TypeError 9640: (92-99): Explicit type conversion not allowed from "int_const 2" to "enum C.Test".
|
||||||
|
// TypeError 9640: (109-117): Explicit type conversion not allowed from "int_const 13" to "enum C.Test".
|
||||||
|
// TypeError 9640: (127-136): Explicit type conversion not allowed from "rational_const 5 / 3" to "enum C.Test".
|
||||||
|
// TypeError 9640: (146-155): Explicit type conversion not allowed from "rational_const 1 / 2" to "enum C.Test".
|
Loading…
Reference in New Issue
Block a user