mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Improves Result<T> in order to prevent defects.
This commit is contained in:
parent
6ac5c52528
commit
b9a7a88346
@ -17,7 +17,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
namespace dev
|
||||
{
|
||||
@ -31,7 +30,7 @@ namespace dev
|
||||
/// Result<bool> check()
|
||||
/// {
|
||||
/// if (false)
|
||||
/// return Result<bool>("Error message.")
|
||||
/// return Result<bool>::err("Error message.")
|
||||
/// return true;
|
||||
/// }
|
||||
///
|
||||
@ -40,8 +39,17 @@ template <class ResultType>
|
||||
class Result
|
||||
{
|
||||
public:
|
||||
Result(ResultType _value): Result(_value, std::string{}) { }
|
||||
Result(std::string _message): Result(ResultType{}, std::move(_message)) { }
|
||||
/// Constructs a result with _value and an empty message.
|
||||
/// This is meant to be called with valid results. Please use
|
||||
/// the static err() member function to signal an error.
|
||||
Result(ResultType _value): Result(_value, std::string{}) {}
|
||||
|
||||
/// Constructs a result with a default-constructed value and an
|
||||
/// error message.
|
||||
static Result<ResultType> err(std::string _message)
|
||||
{
|
||||
return Result{ResultType{}, std::move(_message)};
|
||||
}
|
||||
|
||||
/// @{
|
||||
/// @name Wrapper functions
|
||||
|
@ -129,10 +129,10 @@ bool fitsPrecisionBase2(bigint const& _mantissa, uint32_t _expBase2)
|
||||
BoolResult fitsIntegerType(bigint const& _value, IntegerType const& _type)
|
||||
{
|
||||
if (_value < 0 && !_type.isSigned())
|
||||
return BoolResult{std::string("Cannot implicitly convert signed literal to unsigned type.")};
|
||||
return BoolResult::err("Cannot implicitly convert signed literal to unsigned type.");
|
||||
|
||||
if (_type.minValue() > _value || _value > _type.maxValue())
|
||||
return BoolResult{"Literal is too large to fit in " + _type.toString(false) + "."};
|
||||
return BoolResult::err("Literal is too large to fit in " + _type.toString(false) + ".");
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -535,7 +535,7 @@ TypeResult AddressType::unaryOperatorResult(Token _operator) const
|
||||
TypeResult AddressType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
|
||||
{
|
||||
if (!TokenTraits::isCompareOp(_operator))
|
||||
return TypeResult{"Arithmetic operations on addresses are not supported. Convert to integer first before using them."};
|
||||
return TypeResult::err("Arithmetic operations on addresses are not supported. Convert to integer first before using them.");
|
||||
|
||||
return Type::commonType(shared_from_this(), _other);
|
||||
}
|
||||
@ -638,7 +638,7 @@ TypeResult IntegerType::unaryOperatorResult(Token _operator) const
|
||||
_operator == Token::Dec || _operator == Token::BitNot)
|
||||
return TypeResult{shared_from_this()};
|
||||
else
|
||||
return TypeResult{""};
|
||||
return TypeResult::err("");
|
||||
}
|
||||
|
||||
bool IntegerType::operator==(Type const& _other) const
|
||||
@ -700,7 +700,7 @@ TypeResult IntegerType::binaryOperatorResult(Token _operator, TypePointer const&
|
||||
if (auto intType = dynamic_pointer_cast<IntegerType const>(commonType))
|
||||
{
|
||||
if (Token::Exp == _operator && intType->isSigned())
|
||||
return TypeResult{"Exponentiation is not allowed for signed integer types."};
|
||||
return TypeResult::err("Exponentiation is not allowed for signed integer types.");
|
||||
}
|
||||
else if (auto fixType = dynamic_pointer_cast<FixedPointType const>(commonType))
|
||||
if (Token::Exp == _operator)
|
||||
@ -729,7 +729,7 @@ BoolResult FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) con
|
||||
{
|
||||
FixedPointType const& convertTo = dynamic_cast<FixedPointType const&>(_convertTo);
|
||||
if (convertTo.fractionalDigits() < m_fractionalDigits)
|
||||
return BoolResult{std::string("Too many fractional digits.")};
|
||||
return BoolResult::err("Too many fractional digits.");
|
||||
if (convertTo.numBits() < m_totalBits)
|
||||
return false;
|
||||
else
|
||||
@ -1145,7 +1145,7 @@ TypeResult RationalNumberType::binaryOperatorResult(Token _operator, TypePointer
|
||||
uint32_t absExp = bigint(abs(exp)).convert_to<uint32_t>();
|
||||
|
||||
if (!fitsPrecisionExp(abs(m_value.numerator()), absExp) || !fitsPrecisionExp(abs(m_value.denominator()), absExp))
|
||||
return TypeResult{"Precision of rational constants is limited to 4096 bits."};
|
||||
return TypeResult::err("Precision of rational constants is limited to 4096 bits.");
|
||||
|
||||
static auto const optimizedPow = [](bigint const& _base, uint32_t _exponent) -> bigint {
|
||||
if (_base == 1)
|
||||
@ -1226,7 +1226,7 @@ TypeResult RationalNumberType::binaryOperatorResult(Token _operator, TypePointer
|
||||
|
||||
// verify that numerator and denominator fit into 4096 bit after every operation
|
||||
if (value.numerator() != 0 && max(mostSignificantBit(abs(value.numerator())), mostSignificantBit(abs(value.denominator()))) > 4096)
|
||||
return TypeResult{"Precision of rational constants is limited to 4096 bits."};
|
||||
return TypeResult::err("Precision of rational constants is limited to 4096 bits.");
|
||||
|
||||
return TypeResult(make_shared<RationalNumberType>(value));
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ BOOST_AUTO_TEST_CASE(encoded_sizes)
|
||||
BOOST_AUTO_TEST_CASE(helper_bool_result)
|
||||
{
|
||||
BoolResult r1{true};
|
||||
BoolResult r2{string{"Failure."}};
|
||||
BoolResult r2 = BoolResult::err("Failure.");
|
||||
r1.merge(r2, logical_and<bool>());
|
||||
BOOST_REQUIRE_EQUAL(r1.get(), false);
|
||||
BOOST_REQUIRE_EQUAL(r1.message(), "Failure.");
|
||||
@ -264,13 +264,29 @@ BOOST_AUTO_TEST_CASE(helper_bool_result)
|
||||
BOOST_REQUIRE_EQUAL(r5.message(), "");
|
||||
|
||||
BoolResult r7{true};
|
||||
// Attention: this will implicitely convert to bool.
|
||||
// Attention: this will implicitly convert to bool.
|
||||
BoolResult r8{"true"};
|
||||
r7.merge(r8, logical_and<bool>());
|
||||
BOOST_REQUIRE_EQUAL(r7.get(), true);
|
||||
BOOST_REQUIRE_EQUAL(r7.message(), "");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(helper_string_result)
|
||||
{
|
||||
using StringResult = Result<string>;
|
||||
|
||||
StringResult r1{string{"Success"}};
|
||||
StringResult r2 = StringResult::err("Failure");
|
||||
|
||||
BOOST_REQUIRE_EQUAL(r1.get(), "Success");
|
||||
BOOST_REQUIRE_EQUAL(r2.get(), "");
|
||||
|
||||
r1.merge(r2, [](string const&, string const& _rhs) { return _rhs; });
|
||||
|
||||
BOOST_REQUIRE_EQUAL(r1.get(), "");
|
||||
BOOST_REQUIRE_EQUAL(r1.message(), "Failure");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user