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`.
|
||||
* JSON AST: Removes members with ``null`` value from JSON output.
|
||||
* 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:
|
||||
* 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
|
||||
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::
|
||||
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* 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);
|
||||
|
||||
|
@ -965,10 +965,38 @@ TypeResult RationalNumberType::binaryOperatorResult(Token _operator, Type const*
|
||||
{
|
||||
if (_other->category() == Category::Integer || _other->category() == Category::FixedPoint)
|
||||
{
|
||||
auto commonType = Type::commonType(this, _other);
|
||||
if (!commonType)
|
||||
return nullptr;
|
||||
return commonType->binaryOperatorResult(_operator, _other);
|
||||
if (isFractional())
|
||||
return TypeResult::err("Fractional literals not supported.");
|
||||
else if (!integerType())
|
||||
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())
|
||||
return nullptr;
|
||||
|
@ -1,5 +1,5 @@
|
||||
contract C {
|
||||
function f() public pure returns (uint8 x) {
|
||||
function f() public pure returns (uint x) {
|
||||
uint8 y = uint8(2)**uint8(8);
|
||||
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