mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8994 from ethereum/fixInvertedBinaryOp
Fix type inversion for shift and exp operators.
This commit is contained in:
commit
d12db7ec52
@ -6,6 +6,7 @@ Breaking changes:
|
|||||||
* Deprecated the identifier `now`.
|
* Deprecated the identifier `now`.
|
||||||
* JSON AST: Removes members with ``null`` value from JSON output.
|
* JSON AST: Removes members with ``null`` value from JSON output.
|
||||||
* Type Checker: Disallow shifts by signed types.
|
* Type Checker: Disallow shifts by signed types.
|
||||||
|
* Type Checker: Exponentiation and shifts of literals by non-literals will always use ``uint256`` or ``int256`` as a type.
|
||||||
|
|
||||||
Language Features:
|
Language Features:
|
||||||
* Yul: Disallow EVM instruction `pc()`.
|
* Yul: Disallow EVM instruction `pc()`.
|
||||||
|
@ -444,6 +444,11 @@ long as the operands are integers. If any of the two is fractional, bit operatio
|
|||||||
and exponentiation is disallowed if the exponent is fractional (because that might result in
|
and exponentiation is disallowed if the exponent is fractional (because that might result in
|
||||||
a non-rational number).
|
a non-rational number).
|
||||||
|
|
||||||
|
Shifts and exponentiation with literal numbers as left (or base) operand and integer types
|
||||||
|
as the right (exponent) operand are always performed
|
||||||
|
in the ``uint256`` (for non-negative literals) or ``int256`` (for a negative literals) type,
|
||||||
|
regardless of the type of the right (exponent) operand.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
Division on integer literals used to truncate in Solidity prior to version 0.4.0, but it now converts into a rational number, i.e. ``5 / 2`` is not equal to ``2``, but to ``2.5``.
|
Division on integer literals used to truncate in Solidity prior to version 0.4.0, but it now converts into a rational number, i.e. ``5 / 2`` is not equal to ``2``, but to ``2.5``.
|
||||||
|
|
||||||
|
@ -96,6 +96,7 @@ public:
|
|||||||
static IntegerType const* uint(unsigned _bits) { return integer(_bits, IntegerType::Modifier::Unsigned); }
|
static IntegerType const* uint(unsigned _bits) { return integer(_bits, IntegerType::Modifier::Unsigned); }
|
||||||
|
|
||||||
static IntegerType const* uint256() { return uint(256); }
|
static IntegerType const* uint256() { return uint(256); }
|
||||||
|
static IntegerType const* int256() { return integer(256, IntegerType::Modifier::Signed); }
|
||||||
|
|
||||||
static FixedPointType const* fixedPoint(unsigned m, unsigned n, FixedPointType::Modifier _modifier);
|
static FixedPointType const* fixedPoint(unsigned m, unsigned n, FixedPointType::Modifier _modifier);
|
||||||
|
|
||||||
|
@ -965,10 +965,38 @@ TypeResult RationalNumberType::binaryOperatorResult(Token _operator, Type const*
|
|||||||
{
|
{
|
||||||
if (_other->category() == Category::Integer || _other->category() == Category::FixedPoint)
|
if (_other->category() == Category::Integer || _other->category() == Category::FixedPoint)
|
||||||
{
|
{
|
||||||
auto commonType = Type::commonType(this, _other);
|
if (isFractional())
|
||||||
if (!commonType)
|
return TypeResult::err("Fractional literals not supported.");
|
||||||
return nullptr;
|
else if (!integerType())
|
||||||
return commonType->binaryOperatorResult(_operator, _other);
|
return TypeResult::err("Literal too large.");
|
||||||
|
|
||||||
|
// Shift and exp are not symmetric, so it does not make sense to swap
|
||||||
|
// the types as below. As an exception, we always use uint here.
|
||||||
|
if (TokenTraits::isShiftOp(_operator))
|
||||||
|
{
|
||||||
|
if (!isValidShiftAndAmountType(_operator, *_other))
|
||||||
|
return nullptr;
|
||||||
|
return isNegative() ? TypeProvider::int256() : TypeProvider::uint256();
|
||||||
|
}
|
||||||
|
else if (Token::Exp == _operator)
|
||||||
|
{
|
||||||
|
if (auto const* otherIntType = dynamic_cast<IntegerType const*>(_other))
|
||||||
|
{
|
||||||
|
if (otherIntType->isSigned())
|
||||||
|
return TypeResult::err("Exponentiation power is not allowed to be a signed integer type.");
|
||||||
|
}
|
||||||
|
else if (dynamic_cast<FixedPointType const*>(_other))
|
||||||
|
return TypeResult::err("Exponent is fractional.");
|
||||||
|
|
||||||
|
return isNegative() ? TypeProvider::int256() : TypeProvider::uint256();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto commonType = Type::commonType(this, _other);
|
||||||
|
if (!commonType)
|
||||||
|
return nullptr;
|
||||||
|
return commonType->binaryOperatorResult(_operator, _other);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (_other->category() != category())
|
else if (_other->category() != category())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
contract C {
|
contract C {
|
||||||
function f() public pure returns (uint8 x) {
|
function f() public pure returns (uint x) {
|
||||||
uint8 y = uint8(2)**uint8(8);
|
uint8 y = uint8(2)**uint8(8);
|
||||||
return 0**y;
|
return 0**y;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
contract test {
|
||||||
|
function f(uint x) public pure returns (uint, int) {
|
||||||
|
uint a = 2 ** x;
|
||||||
|
int b = -2 ** x;
|
||||||
|
return (a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// f(uint256): 0 -> 1, 1
|
||||||
|
// f(uint256): 1 -> 2, -2
|
||||||
|
// f(uint256): 2 -> 4, 4
|
||||||
|
// f(uint256): 13 -> 0x2000, -8192
|
||||||
|
// f(uint256): 113 -> 0x020000000000000000000000000000, -10384593717069655257060992658440192
|
||||||
|
// f(uint256): 114 -> 0x040000000000000000000000000000, 20769187434139310514121985316880384
|
||||||
|
// f(uint256): 1113 -> 0x00, 0
|
||||||
|
// f(uint256): 1114 -> 0x00, 0
|
@ -5,4 +5,3 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// Warning: (99-104): Result of exponentiation has type uint8 and thus might overflow. Silence this warning by converting the literal to the expected type.
|
|
||||||
|
@ -5,4 +5,3 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// Warning: (99-106): Result of shift has type uint8 and thus might overflow. Silence this warning by converting the literal to the expected type.
|
|
||||||
|
@ -4,4 +4,4 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (61-77): Operator ** not compatible with types int_const 3 and ufixed128x18
|
// TypeError: (61-77): Operator ** not compatible with types int_const 3 and ufixed128x18. Exponent is fractional.
|
||||||
|
@ -4,4 +4,4 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (61-78): Operator ** not compatible with types int_const 42 and fixed128x18
|
// TypeError: (61-78): Operator ** not compatible with types int_const 42 and fixed128x18. Exponent is fractional.
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
contract test {
|
||||||
|
function f() pure public returns(uint) {
|
||||||
|
uint x = 100;
|
||||||
|
return 10 << x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -7,4 +7,4 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// UnimplementedFeatureError: Not yet implemented - FixedPointType.
|
// TypeError: (117-123): Operator % not compatible with types rational_const 1 / 2 and fixed128x18. Fractional literals not supported.
|
||||||
|
Loading…
Reference in New Issue
Block a user