mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Allow user-defined types as mapping keys in parser and restrict to contracts during type checking.
This commit is contained in:
@@ -2876,6 +2876,25 @@ void TypeChecker::endVisit(Literal const& _literal)
|
||||
_literal.annotation().isPure = true;
|
||||
}
|
||||
|
||||
bool TypeChecker::visit(Mapping const& _mapping)
|
||||
{
|
||||
if (auto const* keyType = dynamic_cast<UserDefinedTypeName const*>(&_mapping.keyType()))
|
||||
{
|
||||
if (
|
||||
keyType->annotation().type->category() != Type::Category::Contract &&
|
||||
keyType->annotation().type->category() != Type::Category::Enum
|
||||
)
|
||||
m_errorReporter.typeError(
|
||||
keyType->location(),
|
||||
"Only elementary types, contract types or enums are allowed as mapping keys."
|
||||
);
|
||||
}
|
||||
else
|
||||
solAssert(dynamic_cast<ElementaryTypeName const*>(&_mapping.keyType()), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool TypeChecker::contractDependenciesAreCyclic(
|
||||
ContractDefinition const& _contract,
|
||||
std::set<ContractDefinition const*> const& _seenContracts
|
||||
|
||||
@@ -143,6 +143,7 @@ private:
|
||||
bool visit(Identifier const& _identifier) override;
|
||||
void endVisit(ElementaryTypeNameExpression const& _expr) override;
|
||||
void endVisit(Literal const& _literal) override;
|
||||
bool visit(Mapping const& _mapping) override;
|
||||
|
||||
bool contractDependenciesAreCyclic(
|
||||
ContractDefinition const& _contract,
|
||||
|
||||
@@ -1152,18 +1152,18 @@ public:
|
||||
Mapping(
|
||||
int64_t _id,
|
||||
SourceLocation const& _location,
|
||||
ASTPointer<ElementaryTypeName> const& _keyType,
|
||||
ASTPointer<TypeName> const& _keyType,
|
||||
ASTPointer<TypeName> const& _valueType
|
||||
):
|
||||
TypeName(_id, _location), m_keyType(_keyType), m_valueType(_valueType) {}
|
||||
void accept(ASTVisitor& _visitor) override;
|
||||
void accept(ASTConstVisitor& _visitor) const override;
|
||||
|
||||
ElementaryTypeName const& keyType() const { return *m_keyType; }
|
||||
TypeName const& keyType() const { return *m_keyType; }
|
||||
TypeName const& valueType() const { return *m_valueType; }
|
||||
|
||||
private:
|
||||
ASTPointer<ElementaryTypeName> m_keyType;
|
||||
ASTPointer<TypeName> m_keyType;
|
||||
ASTPointer<TypeName> m_valueType;
|
||||
};
|
||||
|
||||
|
||||
@@ -511,7 +511,7 @@ ASTPointer<Mapping> ASTJsonImporter::createMapping(Json::Value const& _node)
|
||||
{
|
||||
return createASTNode<Mapping>(
|
||||
_node,
|
||||
createElementaryTypeName(member(_node, "keyType")),
|
||||
convertJsonToASTNode<TypeName>(member(_node, "keyType")),
|
||||
convertJsonToASTNode<TypeName>(member(_node, "valueType"))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1019,16 +1019,22 @@ ASTPointer<Mapping> Parser::parseMapping()
|
||||
ASTNodeFactory nodeFactory(*this);
|
||||
expectToken(Token::Mapping);
|
||||
expectToken(Token::LParen);
|
||||
ASTPointer<ElementaryTypeName> keyType;
|
||||
ASTPointer<TypeName> keyType;
|
||||
Token token = m_scanner->currentToken();
|
||||
if (!TokenTraits::isElementaryTypeName(token))
|
||||
fatalParserError(string("Expected elementary type name for mapping key type"));
|
||||
unsigned firstSize;
|
||||
unsigned secondSize;
|
||||
tie(firstSize, secondSize) = m_scanner->currentTokenInfo();
|
||||
ElementaryTypeNameToken elemTypeName(token, firstSize, secondSize);
|
||||
keyType = ASTNodeFactory(*this).createNode<ElementaryTypeName>(elemTypeName);
|
||||
m_scanner->next();
|
||||
if (token == Token::Identifier)
|
||||
keyType = parseUserDefinedTypeName();
|
||||
else if (TokenTraits::isElementaryTypeName(token))
|
||||
{
|
||||
keyType = ASTNodeFactory(*this).createNode<ElementaryTypeName>(
|
||||
ElementaryTypeNameToken{token, firstSize, secondSize}
|
||||
);
|
||||
m_scanner->next();
|
||||
}
|
||||
else
|
||||
fatalParserError(string("Expected elementary type name or identifier for mapping key type"));
|
||||
expectToken(Token::Arrow);
|
||||
bool const allowVar = false;
|
||||
ASTPointer<TypeName> valueType = parseTypeName(allowVar);
|
||||
|
||||
Reference in New Issue
Block a user