mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[TMP] Replace IdentifierPath with Identifier/Member access for literal suffixes
This commit is contained in:
parent
a5a294053d
commit
d98b12420b
@ -234,10 +234,8 @@ bool FunctionCallGraphBuilder::visit(NewExpression const& _newExpression)
|
|||||||
|
|
||||||
bool FunctionCallGraphBuilder::visit(Literal const& _literal)
|
bool FunctionCallGraphBuilder::visit(Literal const& _literal)
|
||||||
{
|
{
|
||||||
if (auto const* identifierPath = get_if<ASTPointer<IdentifierPath>>(&_literal.suffix()))
|
if (_literal.suffixFunction())
|
||||||
functionReferenced(
|
functionReferenced(*_literal.suffixFunction());
|
||||||
dynamic_cast<FunctionDefinition const&>(*(*identifierPath)->annotation().referencedDeclaration)
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3709,6 +3709,7 @@ void TypeChecker::endVisit(Literal const& _literal)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Literal::SubDenomination const* subDenomination = get_if<Literal::SubDenomination>(&_literal.suffix());
|
Literal::SubDenomination const* subDenomination = get_if<Literal::SubDenomination>(&_literal.suffix());
|
||||||
|
|
||||||
if (_literal.isHexNumber() && subDenomination && *subDenomination != Literal::SubDenomination::None)
|
if (_literal.isHexNumber() && subDenomination && *subDenomination != Literal::SubDenomination::None)
|
||||||
m_errorReporter.fatalTypeError(
|
m_errorReporter.fatalTypeError(
|
||||||
5145_error,
|
5145_error,
|
||||||
@ -3733,14 +3734,21 @@ void TypeChecker::endVisit(Literal const& _literal)
|
|||||||
// TODO at this point 'type' needs to be stored for code generation.
|
// TODO at this point 'type' needs to be stored for code generation.
|
||||||
|
|
||||||
bool isCompileTimeConstant = true;
|
bool isCompileTimeConstant = true;
|
||||||
if (auto const* identifierPath = get_if<ASTPointer<IdentifierPath>>(&_literal.suffix()))
|
if (!subDenomination)
|
||||||
{
|
{
|
||||||
Declaration const* declaration = (*identifierPath)->annotation().referencedDeclaration;
|
FunctionType const* suffixFunctionType = dynamic_cast<FunctionType const*>(std::visit(GenericVisitor{
|
||||||
FunctionDefinition const* definition = dynamic_cast<FunctionDefinition const*>(declaration);
|
[&](ASTPointer<Identifier> const& _identifier) { return _identifier->annotation().type; },
|
||||||
|
[&](ASTPointer<MemberAccess> const& _memberAccess) { return _memberAccess->annotation().type; },
|
||||||
|
[&](Literal::SubDenomination) -> Type const* { solAssert(false); },
|
||||||
|
}, _literal.suffix()));
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!definition ||
|
!suffixFunctionType || // Rejects variables
|
||||||
!definition->isFree() ||
|
!suffixFunctionType->hasDeclaration() || // Rejects function pointers
|
||||||
definition->stateMutability() != StateMutability::Pure
|
!dynamic_cast<FunctionDefinition const*>(&suffixFunctionType->declaration()) || // Rejects events and errors
|
||||||
|
suffixFunctionType->bound() ||
|
||||||
|
!_literal.suffixFunction()->isFree() ||
|
||||||
|
_literal.suffixFunction()->stateMutability() != StateMutability::Pure
|
||||||
)
|
)
|
||||||
m_errorReporter.typeError(
|
m_errorReporter.typeError(
|
||||||
4438_error,
|
4438_error,
|
||||||
@ -3749,24 +3757,23 @@ void TypeChecker::endVisit(Literal const& _literal)
|
|||||||
);
|
);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FunctionType const& functionType = dynamic_cast<FunctionType const&>(*declaration->type());
|
solAssert(!suffixFunctionType->takesArbitraryParameters());
|
||||||
solAssert(!functionType.takesArbitraryParameters());
|
solAssert(suffixFunctionType->kind() == FunctionType::Kind::Internal);
|
||||||
solAssert(functionType.kind() == FunctionType::Kind::Internal);
|
|
||||||
|
|
||||||
auto const* rationalType = dynamic_cast<RationalNumberType const*>(type);
|
auto const* literalRationalType = dynamic_cast<RationalNumberType const*>(type);
|
||||||
|
|
||||||
optional<string> parameterCountMessage;
|
optional<string> parameterCountMessage;
|
||||||
if (functionType.parameterTypes().size() == 0)
|
if (suffixFunctionType->parameterTypes().size() == 0)
|
||||||
parameterCountMessage = "Functions that take no arguments cannot be used as literal suffixes.";
|
parameterCountMessage = "Functions that take no arguments cannot be used as literal suffixes.";
|
||||||
else if (functionType.parameterTypes().size() >= 3)
|
else if (suffixFunctionType->parameterTypes().size() >= 3)
|
||||||
parameterCountMessage = "Functions that take 3 or more arguments cannot be used as literal suffixes.";
|
parameterCountMessage = "Functions that take 3 or more arguments cannot be used as literal suffixes.";
|
||||||
else if (functionType.parameterTypes().size() == 2 && !rationalType)
|
else if (suffixFunctionType->parameterTypes().size() == 2 && !literalRationalType)
|
||||||
parameterCountMessage = "Functions that take 2 arguments can only be used as literal suffixes for rational numbers.";
|
parameterCountMessage = "Functions that take 2 arguments can only be used as literal suffixes for rational numbers.";
|
||||||
|
|
||||||
optional<string> parameterTypeMessage;
|
optional<string> parameterTypeMessage;
|
||||||
if (parameterCountMessage.has_value())
|
if (parameterCountMessage.has_value())
|
||||||
m_errorReporter.typeError(4778_error, _literal.location(), parameterCountMessage.value());
|
m_errorReporter.typeError(4778_error, _literal.location(), parameterCountMessage.value());
|
||||||
else if (functionType.parameterTypes().size() == 2)
|
else if (suffixFunctionType->parameterTypes().size() == 2)
|
||||||
{
|
{
|
||||||
auto&& [mantissa, exponent] = dynamic_cast<RationalNumberType const*>(type)->mantissaExponent();
|
auto&& [mantissa, exponent] = dynamic_cast<RationalNumberType const*>(type)->mantissaExponent();
|
||||||
solAssert((mantissa && exponent) || (!mantissa && !exponent));
|
solAssert((mantissa && exponent) || (!mantissa && !exponent));
|
||||||
@ -3778,25 +3785,27 @@ void TypeChecker::endVisit(Literal const& _literal)
|
|||||||
"that fit the range of parameters of the suffix function."
|
"that fit the range of parameters of the suffix function."
|
||||||
);
|
);
|
||||||
else if (
|
else if (
|
||||||
!mantissa->isImplicitlyConvertibleTo(*functionType.parameterTypes().at(0)) ||
|
!mantissa->isImplicitlyConvertibleTo(*suffixFunctionType->parameterTypes().at(0)) ||
|
||||||
!exponent->isImplicitlyConvertibleTo(*functionType.parameterTypes().at(1))
|
!exponent->isImplicitlyConvertibleTo(*suffixFunctionType->parameterTypes().at(1))
|
||||||
)
|
)
|
||||||
// TODO: Is this triggered when the argument is out of range? Test.
|
// 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.";
|
parameterTypeMessage = "The type of the literal cannot be converted to the parameters of the suffix function.";
|
||||||
}
|
}
|
||||||
else if (!type->isImplicitlyConvertibleTo(*functionType.parameterTypes().front()))
|
else if (!type->isImplicitlyConvertibleTo(*suffixFunctionType->parameterTypes().front()))
|
||||||
parameterTypeMessage = "The type of the literal cannot be converted to the parameter of the suffix function.";
|
parameterTypeMessage = "The type of the literal cannot be converted to the parameter of the suffix function.";
|
||||||
|
|
||||||
if (parameterTypeMessage.has_value())
|
if (parameterTypeMessage.has_value())
|
||||||
m_errorReporter.typeError(8838_error, _literal.location(), parameterTypeMessage.value());
|
m_errorReporter.typeError(8838_error, _literal.location(), parameterTypeMessage.value());
|
||||||
|
|
||||||
isCompileTimeConstant = functionType.isPure();
|
isCompileTimeConstant = suffixFunctionType->isPure();
|
||||||
if (functionType.returnParameterTypes().size() == 1)
|
if (suffixFunctionType->returnParameterTypes().size() == 1)
|
||||||
type = functionType.returnParameterTypes().front();
|
type = suffixFunctionType->returnParameterTypes().front();
|
||||||
else
|
else
|
||||||
type = TypeProvider::tuple(functionType.returnParameterTypes());
|
type = TypeProvider::tuple(suffixFunctionType->returnParameterTypes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
solAssert(holds_alternative<Literal::SubDenomination>(_literal.suffix()));
|
||||||
|
|
||||||
_literal.annotation().type = type;
|
_literal.annotation().type = type;
|
||||||
_literal.annotation().isPure = isCompileTimeConstant;
|
_literal.annotation().isPure = isCompileTimeConstant;
|
||||||
|
@ -27,7 +27,9 @@
|
|||||||
#include <libsolidity/ast/ASTVisitor.h>
|
#include <libsolidity/ast/ASTVisitor.h>
|
||||||
#include <libsolidity/ast/AST_accept.h>
|
#include <libsolidity/ast/AST_accept.h>
|
||||||
#include <libsolidity/ast/TypeProvider.h>
|
#include <libsolidity/ast/TypeProvider.h>
|
||||||
|
|
||||||
#include <libsolutil/Keccak256.h>
|
#include <libsolutil/Keccak256.h>
|
||||||
|
#include <libsolutil/Visitor.h>
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
@ -940,6 +942,23 @@ ASTString Literal::valueWithoutUnderscores() const
|
|||||||
return boost::erase_all_copy(value(), "_");
|
return boost::erase_all_copy(value(), "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FunctionDefinition const* Literal::suffixFunction() const
|
||||||
|
{
|
||||||
|
if (holds_alternative<SubDenomination>(m_suffix))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
Declaration const* referencedDeclaration = visit(util::GenericVisitor{
|
||||||
|
[&](ASTPointer<Identifier> const& _identifier) { return _identifier->annotation().referencedDeclaration; },
|
||||||
|
[&](ASTPointer<MemberAccess> const& _memberAccess) { return _memberAccess->annotation().referencedDeclaration; },
|
||||||
|
[&](SubDenomination) -> Declaration const* { solAssert(false); },
|
||||||
|
}, m_suffix);
|
||||||
|
|
||||||
|
solAssert(referencedDeclaration, "Literal suffix must have a definition.");
|
||||||
|
auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(referencedDeclaration);
|
||||||
|
solAssert(functionDefinition, "Non-denomination literal suffix must be a function.");
|
||||||
|
return functionDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
bool Literal::isHexNumber() const
|
bool Literal::isHexNumber() const
|
||||||
{
|
{
|
||||||
if (token() != Token::Number)
|
if (token() != Token::Number)
|
||||||
|
@ -2351,7 +2351,7 @@ public:
|
|||||||
Week = static_cast<int>(Token::SubWeek),
|
Week = static_cast<int>(Token::SubWeek),
|
||||||
Year = static_cast<int>(Token::SubYear)
|
Year = static_cast<int>(Token::SubYear)
|
||||||
};
|
};
|
||||||
using Suffix = std::variant<SubDenomination, ASTPointer<IdentifierPath>>;
|
using Suffix = std::variant<SubDenomination, ASTPointer<Identifier>, ASTPointer<MemberAccess>>;
|
||||||
Literal(
|
Literal(
|
||||||
int64_t _id,
|
int64_t _id,
|
||||||
SourceLocation const& _location,
|
SourceLocation const& _location,
|
||||||
@ -2371,6 +2371,9 @@ public:
|
|||||||
|
|
||||||
//SubDenomination subDenomination() const { return m_suffix; }
|
//SubDenomination subDenomination() const { return m_suffix; }
|
||||||
Suffix const& suffix() const { return m_suffix; }
|
Suffix const& suffix() const { return m_suffix; }
|
||||||
|
/// @returns Function definition associated with the suffix if the suffix is not a subdenomination.
|
||||||
|
/// nullptr otherwise.
|
||||||
|
FunctionDefinition const* suffixFunction() const;
|
||||||
|
|
||||||
/// @returns true if this is a number with a hex prefix.
|
/// @returns true if this is a number with a hex prefix.
|
||||||
bool isHexNumber() const;
|
bool isHexNumber() const;
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
#include <libsolidity/ast/AST.h>
|
#include <libsolidity/ast/AST.h>
|
||||||
#include <libsolidity/ast/ASTVisitor.h>
|
#include <libsolidity/ast/ASTVisitor.h>
|
||||||
|
|
||||||
|
#include <libsolutil/Visitor.h>
|
||||||
|
|
||||||
namespace solidity::frontend
|
namespace solidity::frontend
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -1015,16 +1017,23 @@ void ElementaryTypeNameExpression::accept(ASTConstVisitor& _visitor) const
|
|||||||
void Literal::accept(ASTVisitor& _visitor)
|
void Literal::accept(ASTVisitor& _visitor)
|
||||||
{
|
{
|
||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
if (auto identifierPath = std::get_if<ASTPointer<IdentifierPath>>(&m_suffix))
|
std::visit(solidity::util::GenericVisitor{
|
||||||
(*identifierPath)->accept(_visitor);
|
[&](ASTPointer<Identifier> const& _identifier) { _identifier->accept(_visitor); },
|
||||||
|
[&](ASTPointer<MemberAccess> const& _memberAccess) { _memberAccess->accept(_visitor); },
|
||||||
|
[&](SubDenomination) {},
|
||||||
|
}, m_suffix);
|
||||||
|
|
||||||
_visitor.endVisit(*this);
|
_visitor.endVisit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Literal::accept(ASTConstVisitor& _visitor) const
|
void Literal::accept(ASTConstVisitor& _visitor) const
|
||||||
{
|
{
|
||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
if (auto identifierPath = std::get_if<ASTPointer<IdentifierPath>>(&m_suffix))
|
std::visit(solidity::util::GenericVisitor{
|
||||||
(*identifierPath)->accept(_visitor);
|
[&](ASTPointer<Identifier> const& _identifier) { _identifier->accept(_visitor); },
|
||||||
|
[&](ASTPointer<MemberAccess> const& _memberAccess) { _memberAccess->accept(_visitor); },
|
||||||
|
[&](SubDenomination) {},
|
||||||
|
}, m_suffix);
|
||||||
_visitor.endVisit(*this);
|
_visitor.endVisit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2271,12 +2271,9 @@ void ExpressionCompiler::endVisit(Literal const& _literal)
|
|||||||
{
|
{
|
||||||
CompilerContext::LocationSetter locationSetter(m_context, _literal);
|
CompilerContext::LocationSetter locationSetter(m_context, _literal);
|
||||||
|
|
||||||
if (auto identifierPath = get_if<ASTPointer<IdentifierPath>>(&_literal.suffix()))
|
if (_literal.suffixDefinition())
|
||||||
{
|
{
|
||||||
FunctionDefinition const& function = dynamic_cast<FunctionDefinition const&>(
|
FunctionType const& functionType = *_literal.suffixDefinition()->functionType(true);
|
||||||
*(*identifierPath)->annotation().referencedDeclaration
|
|
||||||
);
|
|
||||||
FunctionType const& functionType = *function.functionType(true);
|
|
||||||
|
|
||||||
evmasm::AssemblyItem returnLabel = m_context.pushNewTag();
|
evmasm::AssemblyItem returnLabel = m_context.pushNewTag();
|
||||||
|
|
||||||
@ -2298,7 +2295,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal)
|
|||||||
m_context << type->literalValue(&_literal);
|
m_context << type->literalValue(&_literal);
|
||||||
utils().convertType(*type, *functionType.parameterTypes().at(0));
|
utils().convertType(*type, *functionType.parameterTypes().at(0));
|
||||||
}
|
}
|
||||||
m_context << m_context.functionEntryLabel(function).pushTag();
|
m_context << m_context.functionEntryLabel(*_literal.suffixDefinition()).pushTag();
|
||||||
m_context.appendJump(evmasm::AssemblyItem::JumpType::IntoFunction);
|
m_context.appendJump(evmasm::AssemblyItem::JumpType::IntoFunction);
|
||||||
m_context << returnLabel;
|
m_context << returnLabel;
|
||||||
|
|
||||||
@ -2311,6 +2308,8 @@ void ExpressionCompiler::endVisit(Literal const& _literal)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
solAssert(holds_alternative<Literal::SubDenomination>(_literal.suffix()));
|
||||||
|
|
||||||
Type const* type = _literal.annotation().type;
|
Type const* type = _literal.annotation().type;
|
||||||
|
|
||||||
|
|
||||||
|
@ -2438,12 +2438,9 @@ bool IRGeneratorForStatements::visit(Literal const& _literal)
|
|||||||
{
|
{
|
||||||
setLocation(_literal);
|
setLocation(_literal);
|
||||||
|
|
||||||
if (auto identifierPath = get_if<ASTPointer<IdentifierPath>>(&_literal.suffix()))
|
if (_literal.suffixFunction())
|
||||||
{
|
{
|
||||||
FunctionDefinition const& function = dynamic_cast<FunctionDefinition const&>(
|
FunctionType const& functionType = *_literal.suffixFunction()->functionType(true);
|
||||||
*(*identifierPath)->annotation().referencedDeclaration
|
|
||||||
);
|
|
||||||
FunctionType const& functionType = *function.functionType(true);
|
|
||||||
|
|
||||||
// TODO this is actually not always the right one.
|
// TODO this is actually not always the right one.
|
||||||
auto type = TypeProvider::forLiteral(_literal);
|
auto type = TypeProvider::forLiteral(_literal);
|
||||||
@ -2472,11 +2469,12 @@ bool IRGeneratorForStatements::visit(Literal const& _literal)
|
|||||||
// TODO what about string?
|
// TODO what about string?
|
||||||
}
|
}
|
||||||
define(_literal) <<
|
define(_literal) <<
|
||||||
m_context.enqueueFunctionForCodeGeneration(function) <<
|
m_context.enqueueFunctionForCodeGeneration(*_literal.suffixFunction()) <<
|
||||||
"(" + joinHumanReadable(args) + ")\n";
|
"(" + joinHumanReadable(args) + ")\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
solAssert(holds_alternative<Literal::SubDenomination>(_literal.suffix()));
|
||||||
Type const& literalType = type(_literal);
|
Type const& literalType = type(_literal);
|
||||||
|
|
||||||
switch (literalType.category())
|
switch (literalType.category())
|
||||||
|
@ -35,10 +35,12 @@
|
|||||||
#include <boost/algorithm/string/trim.hpp>
|
#include <boost/algorithm/string/trim.hpp>
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <vector>
|
#include <memory>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
@ -1996,9 +1998,31 @@ ASTPointer<Expression> Parser::parseLiteral()
|
|||||||
}
|
}
|
||||||
else if (m_scanner->currentToken() == Token::Identifier)
|
else if (m_scanner->currentToken() == Token::Identifier)
|
||||||
{
|
{
|
||||||
auto identifierPath = parseIdentifierPath();
|
// TODO: Make sure locations are set correctly
|
||||||
nodeFactory.setEndPositionFromNode(identifierPath);
|
ASTPointer<ASTString> suffixName = make_shared<ASTString>(m_scanner->currentLiteral());
|
||||||
suffix = move(identifierPath);
|
nodeFactory.markEndPosition();
|
||||||
|
ASTPointer<Identifier> identifier = nodeFactory.createNode<Identifier>(suffixName);
|
||||||
|
|
||||||
|
advance();
|
||||||
|
|
||||||
|
if (m_scanner->currentToken() != Token::Period)
|
||||||
|
suffix = identifier;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASTPointer<Expression> memberAccess = identifier;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// FIXME: This grabs the semicolon
|
||||||
|
advance();
|
||||||
|
nodeFactory.markEndPosition();
|
||||||
|
SourceLocation memberLocation = currentLocation();
|
||||||
|
ASTPointer<ASTString> memberName = expectIdentifierToken();
|
||||||
|
memberAccess = nodeFactory.createNode<MemberAccess>(memberAccess, move(memberName), move(memberLocation));
|
||||||
|
}
|
||||||
|
while (m_scanner->currentToken() == Token::Period);
|
||||||
|
|
||||||
|
suffix = dynamic_pointer_cast<MemberAccess>(memberAccess);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nodeFactory.createNode<Literal>(initialToken, move(value), move(suffix));
|
return nodeFactory.createNode<Literal>(initialToken, move(value), move(suffix));
|
||||||
}
|
}
|
||||||
|
@ -10,4 +10,4 @@ contract C {
|
|||||||
int d = "a" suffix; // TODO: Should match only string
|
int d = "a" suffix; // TODO: Should match only string
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (216-222): Identifier not found or not unique.
|
// TypeError 2144: (214-222): No matching declaration found after variable lookup.
|
||||||
|
@ -18,4 +18,4 @@ contract C {
|
|||||||
int f = -2.55 iuSuffix; // TODO: Should match only (uint8, uint)
|
int f = -2.55 iuSuffix; // TODO: Should match only (uint8, uint)
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (347-354): Identifier not found or not unique.
|
// 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) {}
|
function iuSuffix(int8, uint) pure returns (uint) {}
|
||||||
|
|
||||||
contract C {
|
contract C {
|
||||||
uint a = 1.27 iuSuffix;
|
uint a = 1.27 iuSuffix; // TODO: Error should say it's ambiguous
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (139-147): Identifier not found or not unique.
|
// TypeError 2144: (134-147): No matching declaration found after variable lookup.
|
||||||
|
@ -2,7 +2,7 @@ function uSuffix(uint8, uint) pure returns (uint) {}
|
|||||||
function uSuffix(uint16, uint) pure returns (uint) {}
|
function uSuffix(uint16, uint) pure returns (uint) {}
|
||||||
|
|
||||||
contract C {
|
contract C {
|
||||||
uint a = 1.27 uSuffix;
|
uint a = 1.27 uSuffix; // TODO: Error should say it's ambiguous
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (139-146): Identifier not found or not unique.
|
// TypeError 2144: (134-146): No matching declaration found after variable lookup.
|
||||||
|
@ -11,4 +11,4 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (263-272): Identifier not found or not unique.
|
// TypeError 2144: (259-272): No matching declaration found after variable lookup.
|
||||||
|
@ -3,8 +3,8 @@ function suffix(uint, uint) pure returns (int) {}
|
|||||||
|
|
||||||
contract C {
|
contract C {
|
||||||
function f() public pure {
|
function f() public pure {
|
||||||
int a = 1 suffix;
|
int a = 1 suffix; // TODO: Error should say it's ambiguous
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (157-163): Identifier not found or not unique.
|
// TypeError 2144: (155-163): No matching declaration found after variable lookup.
|
||||||
|
@ -18,4 +18,4 @@ contract C {
|
|||||||
int f = -255 iuSuffix; // TODO: Should match only uint8
|
int f = -255 iuSuffix; // TODO: Should match only uint8
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (310-317): Identifier not found or not unique.
|
// 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) {}
|
function iuSuffix(int8) pure returns (int) {}
|
||||||
|
|
||||||
contract C {
|
contract C {
|
||||||
int a = 127 iuSuffix;
|
int a = 127 iuSuffix; // TODO: Error should say it's ambiguous
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (123-131): Identifier not found or not unique.
|
// TypeError 2144: (119-131): No matching declaration found after variable lookup.
|
||||||
|
@ -2,7 +2,7 @@ function uSuffix(uint8) pure returns (int) {}
|
|||||||
function uSuffix(uint16) pure returns (int) {}
|
function uSuffix(uint16) pure returns (int) {}
|
||||||
|
|
||||||
contract C {
|
contract C {
|
||||||
int a = 127 uSuffix;
|
int a = 127 uSuffix; // TODO: Error should say it's ambiguous
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (123-130): Identifier not found or not unique.
|
// TypeError 2144: (119-130): No matching declaration found after variable lookup.
|
||||||
|
@ -5,4 +5,4 @@ contract C {
|
|||||||
int a = hex"abcd" suffix; // TODO: Should match only bytes
|
int a = hex"abcd" suffix; // TODO: Should match only bytes
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (141-147): Identifier not found or not unique.
|
// 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) {}
|
function suffix(bytes memory) pure returns (uint) {}
|
||||||
|
|
||||||
contract C {
|
contract C {
|
||||||
uint a = "abcd" suffix;
|
uint a = "abcd" suffix; // TODO: Error should say it's ambiguous
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (141-147): Identifier not found or not unique.
|
// TypeError 2144: (134-147): No matching declaration found after variable lookup.
|
||||||
|
@ -7,4 +7,4 @@ contract C {
|
|||||||
uint b = 1000 a.suffix;
|
uint b = 1000 a.suffix;
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (149-157): Identifier not found or not unique.
|
// TypeError 4438: (144-157): The literal suffix needs to be a pre-defined suffix or a file-level pure function.
|
||||||
|
@ -9,4 +9,4 @@ contract C {
|
|||||||
uint b = 1000 a.suffix;
|
uint b = 1000 a.suffix;
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (169-177): Identifier not found or not unique.
|
// TypeError 4438: (164-177): The literal suffix needs to be a pre-defined suffix or a file-level pure function.
|
||||||
|
@ -4,4 +4,4 @@ contract C {
|
|||||||
function suffix(uint x) external pure returns (uint) { return x; }
|
function suffix(uint x) external pure returns (uint) { return x; }
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (31-42): Identifier not found or not unique.
|
// TypeError 4438: (26-42): The literal suffix needs to be a pre-defined suffix or a file-level pure function.
|
||||||
|
@ -6,4 +6,4 @@ contract C {
|
|||||||
uint x = 1000 L.suffix;
|
uint x = 1000 L.suffix;
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (117-125): Identifier not found or not unique.
|
// TypeError 4438: (112-125): The literal suffix needs to be a pre-defined suffix or a file-level pure function.
|
||||||
|
@ -4,4 +4,4 @@ contract C {
|
|||||||
uint a = 1 this.g;
|
uint a = 1 this.g;
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (48-54): Identifier not found or not unique.
|
// TypeError 4438: (46-54): The literal suffix needs to be a pre-defined suffix or a file-level pure function.
|
||||||
|
@ -4,4 +4,4 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (54-60): Identifier not found or not unique.
|
// TypeError 2144: (52-60): No matching declaration found after variable lookup.
|
||||||
|
@ -8,4 +8,4 @@ contract C is B {
|
|||||||
function suffix(uint x) internal pure override returns (uint) { return x; }
|
function suffix(uint x) internal pure override returns (uint) { return x; }
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError 7920: (127-133): Identifier not found or not unique.
|
// TypeError 4438: (122-133): The literal suffix needs to be a pre-defined suffix or a file-level pure function.
|
||||||
|
Loading…
Reference in New Issue
Block a user