mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #13384 from zemse/develop
Allow named parameters in mapping types
This commit is contained in:
commit
f441e1323a
@ -1,6 +1,7 @@
|
|||||||
### 0.8.18 (unreleased)
|
### 0.8.18 (unreleased)
|
||||||
|
|
||||||
Language Features:
|
Language Features:
|
||||||
|
* Allow named parameters in mapping types.
|
||||||
|
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
|
@ -504,7 +504,7 @@ variableDeclarationTuple:
|
|||||||
variableDeclarationStatement: ((variableDeclaration (Assign expression)?) | (variableDeclarationTuple Assign expression)) Semicolon;
|
variableDeclarationStatement: ((variableDeclaration (Assign expression)?) | (variableDeclarationTuple Assign expression)) Semicolon;
|
||||||
expressionStatement: expression Semicolon;
|
expressionStatement: expression Semicolon;
|
||||||
|
|
||||||
mappingType: Mapping LParen key=mappingKeyType DoubleArrow value=typeName RParen;
|
mappingType: Mapping LParen key=mappingKeyType name=identifier? DoubleArrow value=typeName name=identifier? RParen;
|
||||||
/**
|
/**
|
||||||
* Only elementary types or user defined types are viable as mapping keys.
|
* Only elementary types or user defined types are viable as mapping keys.
|
||||||
*/
|
*/
|
||||||
|
@ -4,12 +4,13 @@
|
|||||||
Mapping Types
|
Mapping Types
|
||||||
=============
|
=============
|
||||||
|
|
||||||
Mapping types use the syntax ``mapping(KeyType => ValueType)`` and variables
|
Mapping types use the syntax ``mapping(KeyType KeyName? => ValueType ValueName?)`` and variables of
|
||||||
of mapping type are declared using the syntax ``mapping(KeyType => ValueType) VariableName``.
|
mapping type are declared using the syntax ``mapping(KeyType KeyName? => ValueType ValueName?)
|
||||||
The ``KeyType`` can be any
|
VariableName``. The ``KeyType`` can be any built-in value type, ``bytes``, ``string``, or any
|
||||||
built-in value type, ``bytes``, ``string``, or any contract or enum type. Other user-defined
|
contract or enum type. Other user-defined or complex types, such as mappings, structs or array types
|
||||||
or complex types, such as mappings, structs or array types are not allowed.
|
are not allowed. ``ValueType`` can be any type, including mappings, arrays and structs. ``KeyName``
|
||||||
``ValueType`` can be any type, including mappings, arrays and structs.
|
and ``ValueName`` are optional (so ``mapping(KeyType => ValueType)`` works as well) and can be any
|
||||||
|
valid identifier that is not a type.
|
||||||
|
|
||||||
You can think of mappings as `hash tables <https://en.wikipedia.org/wiki/Hash_table>`_, which are virtually initialised
|
You can think of mappings as `hash tables <https://en.wikipedia.org/wiki/Hash_table>`_, which are virtually initialised
|
||||||
such that every possible key exists and is mapped to a value whose
|
such that every possible key exists and is mapped to a value whose
|
||||||
@ -29,8 +30,10 @@ of contract functions that are publicly visible.
|
|||||||
These restrictions are also true for arrays and structs that contain mappings.
|
These restrictions are also true for arrays and structs that contain mappings.
|
||||||
|
|
||||||
You can mark state variables of mapping type as ``public`` and Solidity creates a
|
You can mark state variables of mapping type as ``public`` and Solidity creates a
|
||||||
:ref:`getter <visibility-and-getters>` for you. The ``KeyType`` becomes a parameter for the getter.
|
:ref:`getter <visibility-and-getters>` for you. The ``KeyType`` becomes a parameter
|
||||||
If ``ValueType`` is a value type or a struct, the getter returns ``ValueType``.
|
with name ``KeyName`` (if specified) for the getter.
|
||||||
|
If ``ValueType`` is a value type or a struct, the getter returns ``ValueType`` with
|
||||||
|
name ``ValueName`` (if specified).
|
||||||
If ``ValueType`` is an array or a mapping, the getter has one parameter for
|
If ``ValueType`` is an array or a mapping, the getter has one parameter for
|
||||||
each ``KeyType``, recursively.
|
each ``KeyType``, recursively.
|
||||||
|
|
||||||
@ -64,6 +67,25 @@ contract that returns the value at the specified address.
|
|||||||
The example below is a simplified version of an
|
The example below is a simplified version of an
|
||||||
`ERC20 token <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol>`_.
|
`ERC20 token <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol>`_.
|
||||||
``_allowances`` is an example of a mapping type inside another mapping type.
|
``_allowances`` is an example of a mapping type inside another mapping type.
|
||||||
|
|
||||||
|
In the example below, the optional ``KeyName`` and ``ValueName`` are provided for the mapping.
|
||||||
|
It does not affect any contract functionality or bytecode, it only sets the ``name`` field
|
||||||
|
for the inputs and outputs in the ABI for the mapping's getter.
|
||||||
|
|
||||||
|
.. code-block:: solidity
|
||||||
|
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
pragma solidity ^0.8.18;
|
||||||
|
|
||||||
|
contract MappingExampleWithNames {
|
||||||
|
mapping(address user => uint balance) public balances;
|
||||||
|
|
||||||
|
function update(uint newBalance) public {
|
||||||
|
balances[msg.sender] = newBalance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
The example below uses ``_allowances`` to record the amount someone else is allowed to withdraw from your account.
|
The example below uses ``_allowances`` to record the amount someone else is allowed to withdraw from your account.
|
||||||
|
|
||||||
.. code-block:: solidity
|
.. code-block:: solidity
|
||||||
|
@ -267,14 +267,59 @@ void DeclarationTypeChecker::endVisit(Mapping const& _mapping)
|
|||||||
solAssert(dynamic_cast<ElementaryTypeName const*>(&_mapping.keyType()), "");
|
solAssert(dynamic_cast<ElementaryTypeName const*>(&_mapping.keyType()), "");
|
||||||
|
|
||||||
Type const* keyType = _mapping.keyType().annotation().type;
|
Type const* keyType = _mapping.keyType().annotation().type;
|
||||||
|
ASTString keyName = _mapping.keyName();
|
||||||
|
|
||||||
Type const* valueType = _mapping.valueType().annotation().type;
|
Type const* valueType = _mapping.valueType().annotation().type;
|
||||||
|
ASTString valueName = _mapping.valueName();
|
||||||
|
|
||||||
// Convert key type to memory.
|
// Convert key type to memory.
|
||||||
keyType = TypeProvider::withLocationIfReference(DataLocation::Memory, keyType);
|
keyType = TypeProvider::withLocationIfReference(DataLocation::Memory, keyType);
|
||||||
|
|
||||||
// Convert value type to storage reference.
|
// Convert value type to storage reference.
|
||||||
valueType = TypeProvider::withLocationIfReference(DataLocation::Storage, valueType);
|
valueType = TypeProvider::withLocationIfReference(DataLocation::Storage, valueType);
|
||||||
_mapping.annotation().type = TypeProvider::mapping(keyType, valueType);
|
_mapping.annotation().type = TypeProvider::mapping(keyType, keyName, valueType, valueName);
|
||||||
|
|
||||||
|
// Check if parameter names are conflicting.
|
||||||
|
if (!keyName.empty())
|
||||||
|
{
|
||||||
|
auto childMappingType = dynamic_cast<MappingType const*>(valueType);
|
||||||
|
ASTString currentValueName = valueName;
|
||||||
|
bool loop = true;
|
||||||
|
while (loop)
|
||||||
|
{
|
||||||
|
bool isError = false;
|
||||||
|
// Value type is a mapping.
|
||||||
|
if (childMappingType)
|
||||||
|
{
|
||||||
|
// Compare top mapping's key name with child mapping's key name.
|
||||||
|
ASTString childKeyName = childMappingType->keyName();
|
||||||
|
if (keyName == childKeyName)
|
||||||
|
isError = true;
|
||||||
|
|
||||||
|
auto valueType = childMappingType->valueType();
|
||||||
|
currentValueName = childMappingType->valueName();
|
||||||
|
childMappingType = dynamic_cast<MappingType const*>(valueType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Compare top mapping's key name with the value name.
|
||||||
|
if (keyName == currentValueName)
|
||||||
|
isError = true;
|
||||||
|
|
||||||
|
loop = false; // We arrived at the end of mapping recursion.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report error.
|
||||||
|
if (isError)
|
||||||
|
{
|
||||||
|
m_errorReporter.declarationError(
|
||||||
|
1809_error,
|
||||||
|
_mapping.location(),
|
||||||
|
"Conflicting parameter name \"" + keyName + "\" in mapping."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclarationTypeChecker::endVisit(ArrayTypeName const& _typeName)
|
void DeclarationTypeChecker::endVisit(ArrayTypeName const& _typeName)
|
||||||
|
@ -1427,18 +1427,29 @@ public:
|
|||||||
int64_t _id,
|
int64_t _id,
|
||||||
SourceLocation const& _location,
|
SourceLocation const& _location,
|
||||||
ASTPointer<TypeName> _keyType,
|
ASTPointer<TypeName> _keyType,
|
||||||
ASTPointer<TypeName> _valueType
|
ASTPointer<ASTString> _keyName,
|
||||||
|
ASTPointer<TypeName> _valueType,
|
||||||
|
ASTPointer<ASTString> _valueName
|
||||||
):
|
):
|
||||||
TypeName(_id, _location), m_keyType(std::move(_keyType)), m_valueType(std::move(_valueType)) {}
|
TypeName(_id, _location),
|
||||||
|
m_keyType(std::move(_keyType)),
|
||||||
|
m_keyName(std::move(_keyName)),
|
||||||
|
m_valueType(std::move(_valueType)),
|
||||||
|
m_valueName(std::move(_valueName))
|
||||||
|
{}
|
||||||
void accept(ASTVisitor& _visitor) override;
|
void accept(ASTVisitor& _visitor) override;
|
||||||
void accept(ASTConstVisitor& _visitor) const override;
|
void accept(ASTConstVisitor& _visitor) const override;
|
||||||
|
|
||||||
TypeName const& keyType() const { return *m_keyType; }
|
TypeName const& keyType() const { return *m_keyType; }
|
||||||
|
ASTString keyName() const { return *m_keyName; }
|
||||||
TypeName const& valueType() const { return *m_valueType; }
|
TypeName const& valueType() const { return *m_valueType; }
|
||||||
|
ASTString valueName() const { return *m_valueName; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASTPointer<TypeName> m_keyType;
|
ASTPointer<TypeName> m_keyType;
|
||||||
|
ASTPointer<ASTString> m_keyName;
|
||||||
ASTPointer<TypeName> m_valueType;
|
ASTPointer<TypeName> m_valueType;
|
||||||
|
ASTPointer<ASTString> m_valueName;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -598,7 +598,9 @@ bool ASTJsonExporter::visit(Mapping const& _node)
|
|||||||
{
|
{
|
||||||
setJsonNode(_node, "Mapping", {
|
setJsonNode(_node, "Mapping", {
|
||||||
make_pair("keyType", toJson(_node.keyType())),
|
make_pair("keyType", toJson(_node.keyType())),
|
||||||
|
make_pair("keyName", _node.keyName()),
|
||||||
make_pair("valueType", toJson(_node.valueType())),
|
make_pair("valueType", toJson(_node.valueType())),
|
||||||
|
make_pair("valueName", _node.valueName()),
|
||||||
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
|
@ -648,7 +648,9 @@ ASTPointer<Mapping> ASTJsonImporter::createMapping(Json::Value const& _node)
|
|||||||
return createASTNode<Mapping>(
|
return createASTNode<Mapping>(
|
||||||
_node,
|
_node,
|
||||||
convertJsonToASTNode<TypeName>(member(_node, "keyType")),
|
convertJsonToASTNode<TypeName>(member(_node, "keyType")),
|
||||||
convertJsonToASTNode<TypeName>(member(_node, "valueType"))
|
memberAsASTString(_node, "keyName"),
|
||||||
|
convertJsonToASTNode<TypeName>(member(_node, "valueType")),
|
||||||
|
memberAsASTString(_node, "valueName")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,9 +571,9 @@ MagicType const* TypeProvider::meta(Type const* _type)
|
|||||||
return createAndGet<MagicType>(_type);
|
return createAndGet<MagicType>(_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
MappingType const* TypeProvider::mapping(Type const* _keyType, Type const* _valueType)
|
MappingType const* TypeProvider::mapping(Type const* _keyType, ASTString _keyName, Type const* _valueType, ASTString _valueName)
|
||||||
{
|
{
|
||||||
return createAndGet<MappingType>(_keyType, _valueType);
|
return createAndGet<MappingType>(_keyType, _keyName, _valueType, _valueName);
|
||||||
}
|
}
|
||||||
|
|
||||||
UserDefinedValueType const* TypeProvider::userDefinedValueType(UserDefinedValueTypeDefinition const& _definition)
|
UserDefinedValueType const* TypeProvider::userDefinedValueType(UserDefinedValueTypeDefinition const& _definition)
|
||||||
|
@ -195,7 +195,7 @@ public:
|
|||||||
|
|
||||||
static MagicType const* meta(Type const* _type);
|
static MagicType const* meta(Type const* _type);
|
||||||
|
|
||||||
static MappingType const* mapping(Type const* _keyType, Type const* _valueType);
|
static MappingType const* mapping(Type const* _keyType, ASTString _keyName, Type const* _valueType, ASTString _valueName);
|
||||||
|
|
||||||
static UserDefinedValueType const* userDefinedValueType(UserDefinedValueTypeDefinition const& _definition);
|
static UserDefinedValueType const* userDefinedValueType(UserDefinedValueTypeDefinition const& _definition);
|
||||||
|
|
||||||
|
@ -2788,14 +2788,16 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
|
|||||||
m_declaration(&_varDecl)
|
m_declaration(&_varDecl)
|
||||||
{
|
{
|
||||||
auto returnType = _varDecl.annotation().type;
|
auto returnType = _varDecl.annotation().type;
|
||||||
|
ASTString returnName;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (auto mappingType = dynamic_cast<MappingType const*>(returnType))
|
if (auto mappingType = dynamic_cast<MappingType const*>(returnType))
|
||||||
{
|
{
|
||||||
m_parameterTypes.push_back(mappingType->keyType());
|
m_parameterTypes.push_back(mappingType->keyType());
|
||||||
m_parameterNames.emplace_back("");
|
m_parameterNames.push_back(mappingType->keyName());
|
||||||
returnType = mappingType->valueType();
|
returnType = mappingType->valueType();
|
||||||
|
returnName = mappingType->valueName();
|
||||||
}
|
}
|
||||||
else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType))
|
else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType))
|
||||||
{
|
{
|
||||||
@ -2834,7 +2836,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
|
|||||||
DataLocation::Memory,
|
DataLocation::Memory,
|
||||||
returnType
|
returnType
|
||||||
));
|
));
|
||||||
m_returnParameterNames.emplace_back("");
|
m_returnParameterNames.emplace_back(returnName);
|
||||||
}
|
}
|
||||||
|
|
||||||
solAssert(
|
solAssert(
|
||||||
|
@ -1510,8 +1510,8 @@ private:
|
|||||||
class MappingType: public CompositeType
|
class MappingType: public CompositeType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MappingType(Type const* _keyType, Type const* _valueType):
|
MappingType(Type const* _keyType, ASTString _keyName, Type const* _valueType, ASTString _valueName):
|
||||||
m_keyType(_keyType), m_valueType(_valueType) {}
|
m_keyType(_keyType), m_keyName(_keyName), m_valueType(_valueType), m_valueName(_valueName) {}
|
||||||
|
|
||||||
Category category() const override { return Category::Mapping; }
|
Category category() const override { return Category::Mapping; }
|
||||||
|
|
||||||
@ -1531,14 +1531,18 @@ public:
|
|||||||
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override;
|
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override;
|
||||||
|
|
||||||
Type const* keyType() const { return m_keyType; }
|
Type const* keyType() const { return m_keyType; }
|
||||||
|
ASTString keyName() const { return m_keyName; }
|
||||||
Type const* valueType() const { return m_valueType; }
|
Type const* valueType() const { return m_valueType; }
|
||||||
|
ASTString valueName() const { return m_valueName; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<Type const*> decomposition() const override { return {m_valueType}; }
|
std::vector<Type const*> decomposition() const override { return {m_valueType}; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type const* m_keyType;
|
Type const* m_keyType;
|
||||||
|
ASTString m_keyName;
|
||||||
Type const* m_valueType;
|
Type const* m_valueType;
|
||||||
|
ASTString m_valueName;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1187,11 +1187,21 @@ ASTPointer<Mapping> Parser::parseMapping()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
fatalParserError(1005_error, "Expected elementary type name or identifier for mapping key type");
|
fatalParserError(1005_error, "Expected elementary type name or identifier for mapping key type");
|
||||||
|
ASTPointer<ASTString> keyName;
|
||||||
|
if (m_scanner->currentToken() == Token::Identifier)
|
||||||
|
keyName = getLiteralAndAdvance();
|
||||||
|
else
|
||||||
|
keyName = make_shared<ASTString>("");
|
||||||
expectToken(Token::DoubleArrow);
|
expectToken(Token::DoubleArrow);
|
||||||
ASTPointer<TypeName> valueType = parseTypeName();
|
ASTPointer<TypeName> valueType = parseTypeName();
|
||||||
|
ASTPointer<ASTString> valueName;
|
||||||
|
if (m_scanner->currentToken() == Token::Identifier)
|
||||||
|
valueName = getLiteralAndAdvance();
|
||||||
|
else
|
||||||
|
valueName = make_shared<ASTString>("");
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
expectToken(Token::RParen);
|
expectToken(Token::RParen);
|
||||||
return nodeFactory.createNode<Mapping>(keyType, valueType);
|
return nodeFactory.createNode<Mapping>(keyType, keyName, valueType, valueName);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<ParameterList> Parser::parseParameterList(
|
ASTPointer<ParameterList> Parser::parseParameterList(
|
||||||
|
77
test/libsolidity/ABIJson/mapping.sol
Normal file
77
test/libsolidity/ABIJson/mapping.sol
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address owner => mapping(address spender => uint value)) public allowance;
|
||||||
|
mapping(bytes32 => address sender) public commits;
|
||||||
|
mapping(bytes32 => bytes32) public something;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// :test
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// "inputs":
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// "internalType": "address",
|
||||||
|
// "name": "owner",
|
||||||
|
// "type": "address"
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "internalType": "address",
|
||||||
|
// "name": "spender",
|
||||||
|
// "type": "address"
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// "name": "allowance",
|
||||||
|
// "outputs":
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// "internalType": "uint256",
|
||||||
|
// "name": "value",
|
||||||
|
// "type": "uint256"
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// "stateMutability": "view",
|
||||||
|
// "type": "function"
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "inputs":
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// "internalType": "bytes32",
|
||||||
|
// "name": "",
|
||||||
|
// "type": "bytes32"
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// "name": "commits",
|
||||||
|
// "outputs":
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// "internalType": "address",
|
||||||
|
// "name": "sender",
|
||||||
|
// "type": "address"
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// "stateMutability": "view",
|
||||||
|
// "type": "function"
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "inputs":
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// "internalType": "bytes32",
|
||||||
|
// "name": "",
|
||||||
|
// "type": "bytes32"
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// "name": "something",
|
||||||
|
// "outputs":
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// "internalType": "bytes32",
|
||||||
|
// "name": "",
|
||||||
|
// "type": "bytes32"
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// "stateMutability": "view",
|
||||||
|
// "type": "function"
|
||||||
|
// }
|
||||||
|
// ]
|
@ -48,6 +48,7 @@
|
|||||||
"typeName":
|
"typeName":
|
||||||
{
|
{
|
||||||
"id": 3,
|
"id": 3,
|
||||||
|
"keyName": "",
|
||||||
"keyType":
|
"keyType":
|
||||||
{
|
{
|
||||||
"id": 1,
|
"id": 1,
|
||||||
@ -67,6 +68,7 @@
|
|||||||
"typeIdentifier": "t_mapping$_t_address_$_t_address_payable_$",
|
"typeIdentifier": "t_mapping$_t_address_$_t_address_payable_$",
|
||||||
"typeString": "mapping(address => address payable)"
|
"typeString": "mapping(address => address payable)"
|
||||||
},
|
},
|
||||||
|
"valueName": "",
|
||||||
"valueType":
|
"valueType":
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
"typeName":
|
"typeName":
|
||||||
{
|
{
|
||||||
"id": 3,
|
"id": 3,
|
||||||
|
"keyName": "",
|
||||||
"keyType":
|
"keyType":
|
||||||
{
|
{
|
||||||
"id": 1,
|
"id": 1,
|
||||||
@ -40,6 +41,7 @@
|
|||||||
"nodeType": "Mapping",
|
"nodeType": "Mapping",
|
||||||
"src": "17:35:1",
|
"src": "17:35:1",
|
||||||
"typeDescriptions": {},
|
"typeDescriptions": {},
|
||||||
|
"valueName": "",
|
||||||
"valueType":
|
"valueType":
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
|
@ -79,6 +79,7 @@
|
|||||||
"typeName":
|
"typeName":
|
||||||
{
|
{
|
||||||
"id": 8,
|
"id": 8,
|
||||||
|
"keyName": "",
|
||||||
"keyType":
|
"keyType":
|
||||||
{
|
{
|
||||||
"id": 6,
|
"id": 6,
|
||||||
@ -110,6 +111,7 @@
|
|||||||
"typeIdentifier": "t_mapping$_t_contract$_C_$19_$_t_bool_$",
|
"typeIdentifier": "t_mapping$_t_contract$_C_$19_$_t_bool_$",
|
||||||
"typeString": "mapping(contract C => bool)"
|
"typeString": "mapping(contract C => bool)"
|
||||||
},
|
},
|
||||||
|
"valueName": "",
|
||||||
"valueType":
|
"valueType":
|
||||||
{
|
{
|
||||||
"id": 7,
|
"id": 7,
|
||||||
@ -144,6 +146,7 @@
|
|||||||
"typeName":
|
"typeName":
|
||||||
{
|
{
|
||||||
"id": 12,
|
"id": 12,
|
||||||
|
"keyName": "",
|
||||||
"keyType":
|
"keyType":
|
||||||
{
|
{
|
||||||
"id": 10,
|
"id": 10,
|
||||||
@ -163,6 +166,7 @@
|
|||||||
"typeIdentifier": "t_mapping$_t_address_$_t_bool_$",
|
"typeIdentifier": "t_mapping$_t_address_$_t_bool_$",
|
||||||
"typeString": "mapping(address => bool)"
|
"typeString": "mapping(address => bool)"
|
||||||
},
|
},
|
||||||
|
"valueName": "",
|
||||||
"valueType":
|
"valueType":
|
||||||
{
|
{
|
||||||
"id": 11,
|
"id": 11,
|
||||||
@ -197,6 +201,7 @@
|
|||||||
"typeName":
|
"typeName":
|
||||||
{
|
{
|
||||||
"id": 17,
|
"id": 17,
|
||||||
|
"keyName": "",
|
||||||
"keyType":
|
"keyType":
|
||||||
{
|
{
|
||||||
"id": 15,
|
"id": 15,
|
||||||
@ -228,6 +233,7 @@
|
|||||||
"typeIdentifier": "t_mapping$_t_enum$_E_$4_$_t_bool_$",
|
"typeIdentifier": "t_mapping$_t_enum$_E_$4_$_t_bool_$",
|
||||||
"typeString": "mapping(enum C.E => bool)"
|
"typeString": "mapping(enum C.E => bool)"
|
||||||
},
|
},
|
||||||
|
"valueName": "",
|
||||||
"valueType":
|
"valueType":
|
||||||
{
|
{
|
||||||
"id": 16,
|
"id": 16,
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
"typeName":
|
"typeName":
|
||||||
{
|
{
|
||||||
"id": 8,
|
"id": 8,
|
||||||
|
"keyName": "",
|
||||||
"keyType":
|
"keyType":
|
||||||
{
|
{
|
||||||
"id": 6,
|
"id": 6,
|
||||||
@ -81,6 +82,7 @@
|
|||||||
"nodeType": "Mapping",
|
"nodeType": "Mapping",
|
||||||
"src": "40:18:1",
|
"src": "40:18:1",
|
||||||
"typeDescriptions": {},
|
"typeDescriptions": {},
|
||||||
|
"valueName": "",
|
||||||
"valueType":
|
"valueType":
|
||||||
{
|
{
|
||||||
"id": 7,
|
"id": 7,
|
||||||
@ -106,6 +108,7 @@
|
|||||||
"typeName":
|
"typeName":
|
||||||
{
|
{
|
||||||
"id": 12,
|
"id": 12,
|
||||||
|
"keyName": "",
|
||||||
"keyType":
|
"keyType":
|
||||||
{
|
{
|
||||||
"id": 10,
|
"id": 10,
|
||||||
@ -117,6 +120,7 @@
|
|||||||
"nodeType": "Mapping",
|
"nodeType": "Mapping",
|
||||||
"src": "66:24:1",
|
"src": "66:24:1",
|
||||||
"typeDescriptions": {},
|
"typeDescriptions": {},
|
||||||
|
"valueName": "",
|
||||||
"valueType":
|
"valueType":
|
||||||
{
|
{
|
||||||
"id": 11,
|
"id": 11,
|
||||||
@ -142,6 +146,7 @@
|
|||||||
"typeName":
|
"typeName":
|
||||||
{
|
{
|
||||||
"id": 17,
|
"id": 17,
|
||||||
|
"keyName": "",
|
||||||
"keyType":
|
"keyType":
|
||||||
{
|
{
|
||||||
"id": 15,
|
"id": 15,
|
||||||
@ -163,6 +168,7 @@
|
|||||||
"nodeType": "Mapping",
|
"nodeType": "Mapping",
|
||||||
"src": "98:18:1",
|
"src": "98:18:1",
|
||||||
"typeDescriptions": {},
|
"typeDescriptions": {},
|
||||||
|
"valueName": "",
|
||||||
"valueType":
|
"valueType":
|
||||||
{
|
{
|
||||||
"id": 16,
|
"id": 16,
|
||||||
|
@ -287,6 +287,7 @@
|
|||||||
"typeName":
|
"typeName":
|
||||||
{
|
{
|
||||||
"id": 25,
|
"id": 25,
|
||||||
|
"keyName": "",
|
||||||
"keyType":
|
"keyType":
|
||||||
{
|
{
|
||||||
"id": 22,
|
"id": 22,
|
||||||
@ -318,6 +319,7 @@
|
|||||||
"typeIdentifier": "t_mapping$_t_userDefinedValueType$_MyAddress_$18_$_t_userDefinedValueType$_MyUInt_$20_$",
|
"typeIdentifier": "t_mapping$_t_userDefinedValueType$_MyAddress_$18_$_t_userDefinedValueType$_MyUInt_$20_$",
|
||||||
"typeString": "mapping(C.MyAddress => C.MyUInt)"
|
"typeString": "mapping(C.MyAddress => C.MyUInt)"
|
||||||
},
|
},
|
||||||
|
"valueName": "",
|
||||||
"valueType":
|
"valueType":
|
||||||
{
|
{
|
||||||
"id": 24,
|
"id": 24,
|
||||||
|
@ -213,6 +213,7 @@
|
|||||||
"typeName":
|
"typeName":
|
||||||
{
|
{
|
||||||
"id": 25,
|
"id": 25,
|
||||||
|
"keyName": "",
|
||||||
"keyType":
|
"keyType":
|
||||||
{
|
{
|
||||||
"id": 22,
|
"id": 22,
|
||||||
@ -234,6 +235,7 @@
|
|||||||
"nodeType": "Mapping",
|
"nodeType": "Mapping",
|
||||||
"src": "169:28:1",
|
"src": "169:28:1",
|
||||||
"typeDescriptions": {},
|
"typeDescriptions": {},
|
||||||
|
"valueName": "",
|
||||||
"valueType":
|
"valueType":
|
||||||
{
|
{
|
||||||
"id": 24,
|
"id": 24,
|
||||||
|
@ -97,12 +97,16 @@ BOOST_AUTO_TEST_CASE(storage_layout_mapping)
|
|||||||
{"first", TypeProvider::fromElementaryTypeName("uint128")},
|
{"first", TypeProvider::fromElementaryTypeName("uint128")},
|
||||||
{"second", TypeProvider::mapping(
|
{"second", TypeProvider::mapping(
|
||||||
TypeProvider::fromElementaryTypeName("uint8"),
|
TypeProvider::fromElementaryTypeName("uint8"),
|
||||||
TypeProvider::fromElementaryTypeName("uint8")
|
"",
|
||||||
|
TypeProvider::fromElementaryTypeName("uint8"),
|
||||||
|
""
|
||||||
)},
|
)},
|
||||||
{"third", TypeProvider::fromElementaryTypeName("uint16")},
|
{"third", TypeProvider::fromElementaryTypeName("uint16")},
|
||||||
{"final", TypeProvider::mapping(
|
{"final", TypeProvider::mapping(
|
||||||
TypeProvider::fromElementaryTypeName("uint8"),
|
TypeProvider::fromElementaryTypeName("uint8"),
|
||||||
TypeProvider::fromElementaryTypeName("uint8")
|
"",
|
||||||
|
TypeProvider::fromElementaryTypeName("uint8"),
|
||||||
|
""
|
||||||
)},
|
)},
|
||||||
}));
|
}));
|
||||||
BOOST_REQUIRE_EQUAL(u256(4), members.storageSize());
|
BOOST_REQUIRE_EQUAL(u256(4), members.storageSize());
|
||||||
@ -199,8 +203,8 @@ BOOST_AUTO_TEST_CASE(type_identifiers)
|
|||||||
FunctionType metaFun(TypePointers{keccak256fun}, TypePointers{s.type()}, strings{""}, strings{""});
|
FunctionType metaFun(TypePointers{keccak256fun}, TypePointers{s.type()}, strings{""}, strings{""});
|
||||||
BOOST_CHECK_EQUAL(metaFun.identifier(), "t_function_internal_nonpayable$_t_function_keccak256_nonpayable$__$returns$__$_$returns$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$");
|
BOOST_CHECK_EQUAL(metaFun.identifier(), "t_function_internal_nonpayable$_t_function_keccak256_nonpayable$__$returns$__$_$returns$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$");
|
||||||
|
|
||||||
Type const* m = TypeProvider::mapping(TypeProvider::fromElementaryTypeName("bytes32"), s.type());
|
Type const* m = TypeProvider::mapping(TypeProvider::fromElementaryTypeName("bytes32"), "", s.type(), "");
|
||||||
MappingType m2(TypeProvider::fromElementaryTypeName("uint64"), m);
|
MappingType m2(TypeProvider::fromElementaryTypeName("uint64"), "", m, "");
|
||||||
BOOST_CHECK_EQUAL(m2.identifier(), "t_mapping$_t_uint64_$_t_mapping$_t_bytes32_$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$_$");
|
BOOST_CHECK_EQUAL(m2.identifier(), "t_mapping$_t_uint64_$_t_mapping$_t_bytes32_$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$_$");
|
||||||
|
|
||||||
// TypeType is tested with contract
|
// TypeType is tested with contract
|
||||||
|
@ -10,4 +10,6 @@ contract Error2 {
|
|||||||
mapping (address => uint balances; // missing ) before "balances"
|
mapping (address => uint balances; // missing ) before "balances"
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// ParserError 6635: (417-425): Expected ')' but got identifier
|
// ParserError 6635: (425-426): Expected ')' but got ';'
|
||||||
|
// ParserError 6635: (425-426): Expected identifier but got ';'
|
||||||
|
// ParserError 6635: (458-459): Expected ';' but got '}'
|
||||||
|
@ -17,7 +17,8 @@ contract SendCoin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// ParserError 6635: (212-220): Expected ')' but got identifier
|
// ParserError 6635: (235-236): Expected identifier but got '}'
|
||||||
// ParserError 6635: (220-221): Expected ';' but got ')'
|
// ParserError 6635: (276-284): Expected ';' but got 'contract'
|
||||||
// ParserError 9182: (220-221): Function, variable, struct or modifier declaration expected.
|
// ParserError 9182: (276-284): Function, variable, struct or modifier declaration expected.
|
||||||
// Warning 3796: (235-236): Recovered in ContractDefinition at '}'.
|
// Warning 3796: (572-573): Recovered in ContractDefinition at '}'.
|
||||||
|
// ParserError 7858: (574-575): Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition.
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
contract C {
|
||||||
|
mapping(uint a => mapping(uint b => uint c)) public x;
|
||||||
|
constructor() {
|
||||||
|
x[1][2] = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// x(uint256,uint256): 1, 2 -> 3
|
||||||
|
// x(uint256,uint256): 0, 0 -> 0
|
@ -13,3 +13,4 @@ contract Thing is IThing {
|
|||||||
|
|
||||||
mapping(uint256=>Value) public override value;
|
mapping(uint256=>Value) public override value;
|
||||||
}
|
}
|
||||||
|
// ----
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address user => bytes32 ipfs) names;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address => bytes32 ipfs) names;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address user => bytes32) names;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address owner => mapping(address spender => bytes32[] notes)) names;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,5 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address uint => bytes32 ipfs) names;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// ParserError 2314: (36-40): Expected '=>' but got 'uint'
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address owner => bytes32[] note) notes;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address => mapping(address => address) hello) world;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,5 @@
|
|||||||
|
contract test {
|
||||||
|
address owner;
|
||||||
|
mapping(address owner => bytes32 ipfs) names;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,5 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address owner => address owner) owner;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError 1809: (20-59): Conflicting parameter name "owner" in mapping.
|
@ -0,0 +1,7 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address owner => mapping(address owner => address owner)) owner;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError 1809: (45-84): Conflicting parameter name "owner" in mapping.
|
||||||
|
// DeclarationError 1809: (20-85): Conflicting parameter name "owner" in mapping.
|
||||||
|
// DeclarationError 1809: (20-85): Conflicting parameter name "owner" in mapping.
|
@ -0,0 +1,5 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address owner => mapping(address owner => address hello)) world;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError 1809: (20-85): Conflicting parameter name "owner" in mapping.
|
@ -0,0 +1,5 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address owner => mapping(address hello => address owner)) world;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError 1809: (20-85): Conflicting parameter name "owner" in mapping.
|
@ -0,0 +1,5 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address hello => mapping(address owner => address owner)) world;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError 1809: (45-84): Conflicting parameter name "owner" in mapping.
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
function _main(mapping(uint name1 => uint name2) storage map) internal {
|
||||||
|
map[1] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
function _main(mapping(uint name1 => uint) storage map) internal {
|
||||||
|
map[1] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
function _main(mapping(uint => uint name2) storage map) internal {
|
||||||
|
map[1] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
function _main(mapping(uint name1 => mapping(uint name2 => uint name3) name4) storage map) internal {
|
||||||
|
map[1][2] = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
function _main(mapping(uint name1 => uint[] name2) storage map) internal {
|
||||||
|
map[1].push(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,7 @@
|
|||||||
|
contract test {
|
||||||
|
function _main(mapping(uint nameSame => mapping(uint name2 => mapping(uint nameSame => uint name3) name4) name5) storage map) internal {
|
||||||
|
map[1][2][3] = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError 1809: (35-132): Conflicting parameter name "nameSame" in mapping.
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
function _main(mapping(uint name1 => mapping(uint name2 => mapping(uint name3 => uint name4) name5) name6) storage map) internal {
|
||||||
|
map[1][2][3] = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
function(mapping(uint name1 => uint name2) storage) internal stateVariableName;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
function(mapping(uint name1 => uint) storage) internal stateVariableName;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
function(mapping(uint => uint name2) storage) internal stateVariableName;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
function(mapping(uint name1 => mapping(uint name2 => uint name3) name4) storage) internal stateVariableName;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
function(mapping(uint name1 => uint[] name2) storage) internal stateVariableName;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,5 @@
|
|||||||
|
contract test {
|
||||||
|
function(mapping(uint nameSame => mapping(uint name2 => mapping(uint nameSame => uint name3) name4) name5) storage) internal stateVariableName;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError 1809: (29-126): Conflicting parameter name "nameSame" in mapping.
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
function(mapping(uint name1 => mapping(uint name2 => mapping(uint name3 => uint name4) name5) name6) storage) internal stateVariableName;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,9 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(uint name1 => uint name2) map;
|
||||||
|
|
||||||
|
function main() external {
|
||||||
|
mapping(uint name3 => uint name4) storage _map = map;
|
||||||
|
_map[1] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,9 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(uint name1 => uint) map;
|
||||||
|
|
||||||
|
function main() external {
|
||||||
|
mapping(uint => uint name4) storage _map = map;
|
||||||
|
_map[1] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,9 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(uint => uint name2) map;
|
||||||
|
|
||||||
|
function main() external {
|
||||||
|
mapping(uint name3 => uint) storage _map = map;
|
||||||
|
_map[1] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,9 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(uint name1 => mapping(uint name2 => uint name3) name4) map;
|
||||||
|
|
||||||
|
function main() external {
|
||||||
|
mapping(uint name5 => uint name6) storage _map = map[1];
|
||||||
|
_map[1] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,9 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(uint name1 => uint[] name4) map;
|
||||||
|
|
||||||
|
function main() external {
|
||||||
|
mapping(uint name5 => uint[] name6) storage _map = map;
|
||||||
|
_map[1].push(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,10 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(uint name1 => mapping(uint name2 => uint name3) name4) map;
|
||||||
|
|
||||||
|
function main() external {
|
||||||
|
mapping(uint nameSame => mapping(uint name2 => uint nameSame) name4) storage _map = map;
|
||||||
|
_map[1][2] = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError 1809: (128-196): Conflicting parameter name "nameSame" in mapping.
|
@ -0,0 +1,11 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(uint nameSame => mapping(uint name1 => mapping(uint nameSame => uint name3) name6) name4) map;
|
||||||
|
|
||||||
|
function main() external {
|
||||||
|
mapping(uint nameSame => mapping(uint name1 => mapping(uint nameSame => uint name3) name6) name4) storage _map = map;
|
||||||
|
_map[1][2][3] = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError 1809: (20-117): Conflicting parameter name "nameSame" in mapping.
|
||||||
|
// DeclarationError 1809: (163-260): Conflicting parameter name "nameSame" in mapping.
|
@ -0,0 +1,9 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(uint name1 => mapping(uint name2 => mapping(uint name3 => uint name4) name5) name6) map;
|
||||||
|
|
||||||
|
function main() external {
|
||||||
|
mapping(uint name1 => mapping(uint name2 => mapping(uint name3 => uint name4) name5) name6) storage _map = map;
|
||||||
|
_map[1][2][3] = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address owner => mapping(address spender => bytes32 note)) names;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address => mapping(address spender => bytes32 note)) names;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address owner => mapping(address => bytes32 note)) names;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address owner => mapping(address spender => bytes32)) names;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,5 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(address owner => mapping(address spender => bytes32 note));
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// ParserError 2314: (86-87): Expected identifier but got ';'
|
@ -0,0 +1,5 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(uint nameSame => mapping(uint name1 => mapping(uint nameSame => uint name2) name3) name4) name5;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError 1809: (20-117): Conflicting parameter name "nameSame" in mapping.
|
@ -0,0 +1,5 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(uint nameSame => mapping(uint name1 => mapping(uint nameSame => uint name3) name6) name4) public name5;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError 1809: (20-117): Conflicting parameter name "nameSame" in mapping.
|
@ -0,0 +1,4 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(uint name1 => mapping(uint name2 => mapping(uint name3 => uint name4) name5) name6) public name7;
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
struct Person {
|
||||||
|
mapping(uint phone => uint calls) friends;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
struct Person {
|
||||||
|
mapping(uint phone => uint) friends;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
struct Person {
|
||||||
|
mapping(uint => uint calls) friends;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
struct Person {
|
||||||
|
mapping(uint phone => mapping(uint call => uint time) callTimes) friends;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
struct Person {
|
||||||
|
mapping(uint phone => uint[] calls) friends;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,7 @@
|
|||||||
|
contract test {
|
||||||
|
struct Person {
|
||||||
|
mapping(uint nameSame => mapping(uint name1 => mapping(uint nameSame => uint name2) name3) name4) name5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError 1809: (44-141): Conflicting parameter name "nameSame" in mapping.
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
struct Person {
|
||||||
|
mapping(uint name1 => mapping(uint name2 => mapping(uint name3 => uint name4) name5) name6) name7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -2,3 +2,4 @@ type MyInt is int;
|
|||||||
contract C {
|
contract C {
|
||||||
mapping(MyInt => int) m;
|
mapping(MyInt => int) m;
|
||||||
}
|
}
|
||||||
|
// ----
|
||||||
|
Loading…
Reference in New Issue
Block a user