mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[TMP] suffixedLiteral annotation and overloading
This commit is contained in:
parent
b815483fc3
commit
2d7a031d47
@ -3560,9 +3560,28 @@ bool TypeChecker::visit(Identifier const& _identifier)
|
||||
|
||||
for (Declaration const* declaration: annotation.overloadedDeclarations)
|
||||
{
|
||||
FunctionTypePointer functionType = declaration->functionType(true);
|
||||
FunctionTypePointer functionType = declaration->functionType(true /* _internal */);
|
||||
solAssert(!!functionType, "Requested type not present.");
|
||||
|
||||
bool argumentsMatch = false;
|
||||
if (functionType->canTakeArguments(*annotation.arguments))
|
||||
argumentsMatch = true;
|
||||
else if (_identifier.annotation().suffixedLiteral && functionType->parameterTypes().size() == 2)
|
||||
{
|
||||
Type const* literalType = _identifier.annotation().suffixedLiteral->annotation().type;
|
||||
auto const* literalRationalType = dynamic_cast<RationalNumberType const*>(literalType);
|
||||
if (literalRationalType)
|
||||
{
|
||||
auto&& [mantissa, exponent] = literalRationalType->mantissaExponent();
|
||||
// This was already validated in visit(Literal) but the error is not fatal.
|
||||
if (!mantissa || !exponent)
|
||||
solAssert(!m_errorReporter.errors().empty());
|
||||
else
|
||||
argumentsMatch = functionType->canTakeArguments({{mantissa, exponent}, {}});
|
||||
}
|
||||
}
|
||||
|
||||
if (argumentsMatch)
|
||||
candidates.push_back(declaration);
|
||||
}
|
||||
if (candidates.size() == 1)
|
||||
@ -3676,7 +3695,7 @@ void TypeChecker::endVisit(ElementaryTypeNameExpression const& _expr)
|
||||
_expr.annotation().isConstant = false;
|
||||
}
|
||||
|
||||
void TypeChecker::endVisit(Literal const& _literal)
|
||||
bool TypeChecker::visit(Literal const& _literal)
|
||||
{
|
||||
Type const* type = nullptr;
|
||||
if (_literal.looksLikeAddress())
|
||||
@ -3733,8 +3752,45 @@ void TypeChecker::endVisit(Literal const& _literal)
|
||||
|
||||
// TODO at this point 'type' needs to be stored for code generation.
|
||||
|
||||
std::visit(GenericVisitor{
|
||||
[&](ASTPointer<Identifier> const& _identifier) {
|
||||
_identifier->annotation().suffixedLiteral = &_literal;
|
||||
_identifier->annotation().arguments = {{type}, {}};
|
||||
},
|
||||
[&](ASTPointer<MemberAccess> const& _memberAccess) {
|
||||
_memberAccess->annotation().suffixedLiteral = &_literal;
|
||||
_memberAccess->annotation().arguments = {{type}, {}};
|
||||
},
|
||||
[&](Literal::SubDenomination) {},
|
||||
}, _literal.suffix());
|
||||
|
||||
auto const* literalRationalType = dynamic_cast<RationalNumberType const*>(type);
|
||||
if (!subDenomination && literalRationalType)
|
||||
{
|
||||
auto&& [mantissa, exponent] = literalRationalType->mantissaExponent();
|
||||
solAssert((mantissa && exponent) || (!mantissa && !exponent));
|
||||
if (!mantissa)
|
||||
m_errorReporter.typeError(
|
||||
5503_error,
|
||||
_literal.location(),
|
||||
"This fractional number cannot be decomposed into a mantissa and decimal exponent "
|
||||
"that fit the range of parameters of any possible suffix function."
|
||||
);
|
||||
}
|
||||
|
||||
// NOTE: For suffixed literals this is not the final type yet. We will update it in endVisit()
|
||||
// when we know what the suffix function returns.
|
||||
_literal.annotation().type = type;
|
||||
_literal.annotation().isLValue = false;
|
||||
_literal.annotation().isConstant = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TypeChecker::endVisit(Literal const& _literal)
|
||||
{
|
||||
bool isCompileTimeConstant = true;
|
||||
if (!subDenomination)
|
||||
if (!holds_alternative<Literal::SubDenomination>(_literal.suffix()))
|
||||
{
|
||||
FunctionType const* suffixFunctionType = dynamic_cast<FunctionType const*>(std::visit(GenericVisitor{
|
||||
[&](ASTPointer<Identifier> const& _identifier) { return _identifier->annotation().type; },
|
||||
@ -3760,7 +3816,8 @@ void TypeChecker::endVisit(Literal const& _literal)
|
||||
solAssert(!suffixFunctionType->takesArbitraryParameters());
|
||||
solAssert(suffixFunctionType->kind() == FunctionType::Kind::Internal);
|
||||
|
||||
auto const* literalRationalType = dynamic_cast<RationalNumberType const*>(type);
|
||||
Type const* literalType = _literal.annotation().type;
|
||||
auto const* literalRationalType = dynamic_cast<RationalNumberType const*>(literalType);
|
||||
|
||||
optional<string> parameterCountMessage;
|
||||
if (suffixFunctionType->parameterTypes().size() == 0)
|
||||
@ -3775,15 +3832,12 @@ void TypeChecker::endVisit(Literal const& _literal)
|
||||
m_errorReporter.typeError(4778_error, _literal.location(), parameterCountMessage.value());
|
||||
else if (suffixFunctionType->parameterTypes().size() == 2)
|
||||
{
|
||||
auto&& [mantissa, exponent] = dynamic_cast<RationalNumberType const*>(type)->mantissaExponent();
|
||||
solAssert((mantissa && exponent) || (!mantissa && !exponent));
|
||||
if (!mantissa)
|
||||
m_errorReporter.typeError(
|
||||
5503_error,
|
||||
_literal.location(),
|
||||
"This fractional number cannot be decomposed into a mantissa and decimal exponent "
|
||||
"that fit the range of parameters of the suffix function."
|
||||
);
|
||||
solAssert(literalRationalType);
|
||||
|
||||
auto&& [mantissa, exponent] = literalRationalType->mantissaExponent();
|
||||
// This was already validated in visit(Literal) but the error is not fatal.
|
||||
if (!mantissa || !exponent)
|
||||
solAssert(!m_errorReporter.errors().empty());
|
||||
else if (
|
||||
!mantissa->isImplicitlyConvertibleTo(*suffixFunctionType->parameterTypes().at(0)) ||
|
||||
!exponent->isImplicitlyConvertibleTo(*suffixFunctionType->parameterTypes().at(1))
|
||||
@ -3791,26 +3845,22 @@ void TypeChecker::endVisit(Literal const& _literal)
|
||||
// TODO: Is this triggered when the argument is out of range? Test.
|
||||
parameterTypeMessage = "The type of the literal cannot be converted to the parameters of the suffix function.";
|
||||
}
|
||||
else if (!type->isImplicitlyConvertibleTo(*suffixFunctionType->parameterTypes().front()))
|
||||
else if (!literalType->isImplicitlyConvertibleTo(*suffixFunctionType->parameterTypes().front()))
|
||||
parameterTypeMessage = "The type of the literal cannot be converted to the parameter of the suffix function.";
|
||||
|
||||
if (parameterTypeMessage.has_value())
|
||||
m_errorReporter.typeError(8838_error, _literal.location(), parameterTypeMessage.value());
|
||||
|
||||
isCompileTimeConstant = suffixFunctionType->isPure();
|
||||
if (suffixFunctionType->returnParameterTypes().size() == 1)
|
||||
type = suffixFunctionType->returnParameterTypes().front();
|
||||
_literal.annotation().type = suffixFunctionType->returnParameterTypes().front();
|
||||
else
|
||||
type = TypeProvider::tuple(suffixFunctionType->returnParameterTypes());
|
||||
_literal.annotation().type = TypeProvider::tuple(suffixFunctionType->returnParameterTypes());
|
||||
|
||||
isCompileTimeConstant = suffixFunctionType->isPure();
|
||||
}
|
||||
}
|
||||
else
|
||||
solAssert(holds_alternative<Literal::SubDenomination>(_literal.suffix()));
|
||||
|
||||
_literal.annotation().type = type;
|
||||
_literal.annotation().isPure = isCompileTimeConstant;
|
||||
_literal.annotation().isLValue = false;
|
||||
_literal.annotation().isConstant = false;
|
||||
}
|
||||
|
||||
void TypeChecker::endVisit(UsingForDirective const& _usingFor)
|
||||
|
@ -164,6 +164,7 @@ private:
|
||||
void endVisit(IdentifierPath const& _identifierPath) override;
|
||||
void endVisit(UserDefinedTypeName const& _userDefinedTypeName) override;
|
||||
void endVisit(ElementaryTypeNameExpression const& _expr) override;
|
||||
bool visit(Literal const& _literal) override;
|
||||
void endVisit(Literal const& _literal) override;
|
||||
void endVisit(UsingForDirective const& _usingForDirective) override;
|
||||
|
||||
|
@ -302,6 +302,8 @@ struct IdentifierAnnotation: ExpressionAnnotation
|
||||
std::vector<Declaration const*> candidateDeclarations;
|
||||
/// List of possible declarations it could refer to.
|
||||
std::vector<Declaration const*> overloadedDeclarations;
|
||||
/// If the identifier is used as a literal suffix, this points at the literal.
|
||||
Literal const* suffixedLiteral = nullptr;
|
||||
};
|
||||
|
||||
struct MemberAccessAnnotation: ExpressionAnnotation
|
||||
@ -310,6 +312,8 @@ struct MemberAccessAnnotation: ExpressionAnnotation
|
||||
Declaration const* referencedDeclaration = nullptr;
|
||||
/// What kind of lookup needs to be done (static, virtual, super) find the declaration.
|
||||
util::SetOnce<VirtualLookup> requiredLookup;
|
||||
/// If the expression is used as a literal suffix, this points at the literal.
|
||||
Literal const* suffixedLiteral = nullptr;
|
||||
};
|
||||
|
||||
struct BinaryOperationAnnotation: ExpressionAnnotation
|
||||
|
@ -43,7 +43,7 @@ contract C {
|
||||
// TypeError 8838: (827-837): The type of the literal cannot be converted to the parameters of the suffix function.
|
||||
// TypeError 8838: (847-857): The type of the literal cannot be converted to the parameters of the suffix function.
|
||||
// TypeError 8838: (867-950): The type of the literal cannot be converted to the parameters of the suffix function.
|
||||
// TypeError 5503: (980-1064): This fractional number cannot be decomposed into a mantissa and decimal exponent that fit the range of parameters of the suffix function.
|
||||
// TypeError 5503: (980-1064): This fractional number cannot be decomposed into a mantissa and decimal exponent that fit the range of parameters of any possible suffix function.
|
||||
// TypeError 8838: (1095-1105): The type of the literal cannot be converted to the parameters of the suffix function.
|
||||
// TypeError 8838: (1115-1125): The type of the literal cannot be converted to the parameters of the suffix function.
|
||||
// TypeError 8838: (1135-1148): The type of the literal cannot be converted to the parameters of the suffix function.
|
||||
|
@ -1,13 +1,12 @@
|
||||
function suffix(uint) pure returns (int) {}
|
||||
function suffix(bool) pure returns (int) {}
|
||||
function suffix(address) pure returns (int) {}
|
||||
function suffix(string memory) pure returns (int) {}
|
||||
function suffix(bool) pure returns (bool) {}
|
||||
function suffix(address) pure returns (address) {}
|
||||
function suffix(string memory) pure returns (string memory) {}
|
||||
|
||||
contract C {
|
||||
int a = 1 suffix; // TODO: Should match only uint
|
||||
int b = true suffix; // TODO: Should match only bool
|
||||
int c = 0x1234567890123456789012345678901234567890 suffix; // TODO: Should match only address
|
||||
int d = "a" suffix; // TODO: Should match only string
|
||||
int a = 1 suffix;
|
||||
bool b = true suffix;
|
||||
address c = 0x1234567890123456789012345678901234567890 suffix;
|
||||
string d = "a" suffix;
|
||||
}
|
||||
// ----
|
||||
// TypeError 2144: (214-222): No matching declaration found after variable lookup.
|
||||
|
@ -1,21 +1,19 @@
|
||||
function uSuffix(uint8, uint) pure returns (int) {}
|
||||
function uSuffix(uint16, uint) pure returns (int) {}
|
||||
function uSuffix(uint8, uint) pure returns (int8) {}
|
||||
function uSuffix(uint16, uint) pure returns (int16) {}
|
||||
|
||||
function iSuffix(int8, uint) pure returns (int) {}
|
||||
function iSuffix(int16, uint) pure returns (int) {}
|
||||
function iSuffix(int8, uint) pure returns (int24) {}
|
||||
function iSuffix(int16, uint) pure returns (int32) {}
|
||||
|
||||
function iuSuffix(uint8, uint) pure returns (int) {}
|
||||
function iuSuffix(int8, uint) pure returns (int) {}
|
||||
function iuSuffix(uint8, uint) pure returns (int40) {}
|
||||
function iuSuffix(int8, uint) pure returns (int48) {}
|
||||
|
||||
contract C {
|
||||
int a = 1.024 uSuffix; // TODO: Should match only (uint16, uint)
|
||||
int b = 1.024 iSuffix; // TODO: Should match only (int16, uint)
|
||||
int16 a = 1.024 uSuffix;
|
||||
int32 b = 1.024 iSuffix;
|
||||
|
||||
int c = -1.024 uSuffix; // TODO: Should match only (uint16, uint)
|
||||
int d = -1.024 iSuffix; // TODO: Should match only (int16, uint)
|
||||
int16 c = -1.024 uSuffix;
|
||||
int32 d = -1.024 iSuffix;
|
||||
|
||||
int e = 2.55 iuSuffix; // TODO: Should match only (uint8, uint)
|
||||
int f = -2.55 iuSuffix; // TODO: Should match only (uint8, uint)
|
||||
int40 e = 2.55 iuSuffix;
|
||||
int40 f = -2.55 iuSuffix;
|
||||
}
|
||||
// ----
|
||||
// TypeError 2144: (341-354): No matching declaration found after variable lookup.
|
||||
|
@ -2,7 +2,7 @@ function iuSuffix(uint8, uint) pure returns (uint) {}
|
||||
function iuSuffix(int8, uint) pure returns (uint) {}
|
||||
|
||||
contract C {
|
||||
uint a = 1.27 iuSuffix; // TODO: Error should say it's ambiguous
|
||||
uint a = 1.27 iuSuffix;
|
||||
}
|
||||
// ----
|
||||
// TypeError 2144: (134-147): No matching declaration found after variable lookup.
|
||||
// TypeError 4487: (134-147): No unique declaration found after argument-dependent lookup.
|
||||
|
@ -2,7 +2,7 @@ function uSuffix(uint8, uint) pure returns (uint) {}
|
||||
function uSuffix(uint16, uint) pure returns (uint) {}
|
||||
|
||||
contract C {
|
||||
uint a = 1.27 uSuffix; // TODO: Error should say it's ambiguous
|
||||
uint a = 1.27 uSuffix;
|
||||
}
|
||||
// ----
|
||||
// TypeError 2144: (134-146): No matching declaration found after variable lookup.
|
||||
// TypeError 4487: (134-146): No unique declaration found after argument-dependent lookup.
|
||||
|
@ -1,14 +1,11 @@
|
||||
function suffix256(uint) pure returns (int) {}
|
||||
function suffix256(uint) pure returns (uint) {}
|
||||
function suffix256(uint, uint) pure returns (int) {}
|
||||
|
||||
function suffix8(uint) pure returns (int) {}
|
||||
function suffix8(uint8, uint) pure returns (int) {}
|
||||
function suffix8(uint) pure returns (uint8) {}
|
||||
function suffix8(uint8, uint) pure returns (int8) {}
|
||||
|
||||
contract C {
|
||||
function f() public pure {
|
||||
int a = 1.1 suffix256; // TODO: Should match only (uint, uint)
|
||||
int b = 1024 suffix8; // TODO: Should match only uint
|
||||
}
|
||||
int a = 1.1 suffix256;
|
||||
uint8 b = 1024 suffix8;
|
||||
}
|
||||
// ----
|
||||
// TypeError 2144: (259-272): No matching declaration found after variable lookup.
|
||||
|
@ -3,8 +3,8 @@ function suffix(uint, uint) pure returns (int) {}
|
||||
|
||||
contract C {
|
||||
function f() public pure {
|
||||
int a = 1 suffix; // TODO: Error should say it's ambiguous
|
||||
int a = 1 suffix;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 2144: (155-163): No matching declaration found after variable lookup.
|
||||
// TypeError 4487: (155-163): No unique declaration found after argument-dependent lookup.
|
||||
|
@ -1,21 +1,19 @@
|
||||
function uSuffix(uint8) pure returns (int) {}
|
||||
function uSuffix(uint16) pure returns (int) {}
|
||||
function uSuffix(uint8) pure returns (int8) {}
|
||||
function uSuffix(uint16) pure returns (int16) {}
|
||||
|
||||
function iSuffix(int8) pure returns (int) {}
|
||||
function iSuffix(int16) pure returns (int) {}
|
||||
function iSuffix(int8) pure returns (int24) {}
|
||||
function iSuffix(int16) pure returns (int32) {}
|
||||
|
||||
function iuSuffix(uint8) pure returns (int) {}
|
||||
function iuSuffix(int8) pure returns (int) {}
|
||||
function iuSuffix(uint8) pure returns (int40) {}
|
||||
function iuSuffix(int8) pure returns (int48) {}
|
||||
|
||||
contract C {
|
||||
int a = 1024 uSuffix; // TODO: Should match only uint16
|
||||
int b = 1024 iSuffix; // TODO: Should match only int16
|
||||
int16 a = 1024 uSuffix;
|
||||
int32 b = 1024 iSuffix;
|
||||
|
||||
int c = -1024 uSuffix; // TODO: Should match only uint16
|
||||
int d = -1024 iSuffix; // TODO: Should match only int16
|
||||
int16 c = -1024 uSuffix;
|
||||
int32 d = -1024 iSuffix;
|
||||
|
||||
int e = 255 iuSuffix; // TODO: Should match only uint8
|
||||
int f = -255 iuSuffix; // TODO: Should match only uint8
|
||||
int40 e = 255 iuSuffix;
|
||||
int40 f = -255 iuSuffix;
|
||||
}
|
||||
// ----
|
||||
// TypeError 2144: (305-317): No matching declaration found after variable lookup.
|
||||
|
@ -2,7 +2,7 @@ function iuSuffix(uint8) pure returns (int) {}
|
||||
function iuSuffix(int8) pure returns (int) {}
|
||||
|
||||
contract C {
|
||||
int a = 127 iuSuffix; // TODO: Error should say it's ambiguous
|
||||
int a = 127 iuSuffix;
|
||||
}
|
||||
// ----
|
||||
// TypeError 2144: (119-131): No matching declaration found after variable lookup.
|
||||
// TypeError 4487: (119-131): No unique declaration found after argument-dependent lookup.
|
||||
|
@ -2,7 +2,7 @@ function uSuffix(uint8) pure returns (int) {}
|
||||
function uSuffix(uint16) pure returns (int) {}
|
||||
|
||||
contract C {
|
||||
int a = 127 uSuffix; // TODO: Error should say it's ambiguous
|
||||
int a = 127 uSuffix;
|
||||
}
|
||||
// ----
|
||||
// TypeError 2144: (119-130): No matching declaration found after variable lookup.
|
||||
// TypeError 4487: (119-130): No unique declaration found after argument-dependent lookup.
|
||||
|
@ -1,8 +1,6 @@
|
||||
function suffix(string memory) pure returns (int) {}
|
||||
function suffix(bytes memory) pure returns (int) {}
|
||||
function suffix(string memory) pure returns (string memory) {}
|
||||
function suffix(bytes memory) pure returns (bytes memory) {}
|
||||
|
||||
contract C {
|
||||
int a = hex"abcd" suffix; // TODO: Should match only bytes
|
||||
bytes a = hex"abcd" suffix;
|
||||
}
|
||||
// ----
|
||||
// TypeError 2144: (131-147): No matching declaration found after variable lookup.
|
||||
|
@ -2,7 +2,7 @@ function suffix(string memory) pure returns (uint) {}
|
||||
function suffix(bytes memory) pure returns (uint) {}
|
||||
|
||||
contract C {
|
||||
uint a = "abcd" suffix; // TODO: Error should say it's ambiguous
|
||||
uint a = "abcd" suffix;
|
||||
}
|
||||
// ----
|
||||
// TypeError 2144: (134-147): No matching declaration found after variable lookup.
|
||||
// TypeError 4487: (134-147): No unique declaration found after argument-dependent lookup.
|
||||
|
@ -9,4 +9,4 @@ contract C {
|
||||
Decimal x = 0.115792089237316195423570985008687907853269984665640564039457584007913129639936 suffix; // 2**256 * 10**-78
|
||||
}
|
||||
// ----
|
||||
// TypeError 5503: (204-291): This fractional number cannot be decomposed into a mantissa and decimal exponent that fit the range of parameters of the suffix function.
|
||||
// TypeError 5503: (204-291): This fractional number cannot be decomposed into a mantissa and decimal exponent that fit the range of parameters of any possible suffix function.
|
||||
|
@ -4,4 +4,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 2144: (52-60): No matching declaration found after variable lookup.
|
||||
// TypeError 9322: (52-60): No matching declaration found after argument-dependent lookup.
|
||||
|
Loading…
Reference in New Issue
Block a user